我具有从调查表创建的以下数据框:
id <- c(1, 2, 3, 4, 5)
type <- c("1,2,3", "2", "2,3,4", "4", "1")
ex_df <- data.frame(id, a, stringsAsFactors=F)
ex_df$type
是类字符,每个数字代表一种棋子:
1 = pawn
2 = rook
3 = knight
4 = bishop
我想根据ex_df$type
列中的字符为每种表示存在/不存在的棋子创建一个单独的列,其中1
表示该棋子在列表中,而0
则表示该棋子在列表中不是。
最终数据帧应如下所示:
'data.frame': 5 obs. of 6 variables:
$ id : num 1 2 3 4 5
$ type : chr "1,2,3" "2" "2,3,4" "4" ...
$ pawn : num 1 0 0 0 1
$ rook : num 1 1 1 0 0
$ knight: num 1 0 1 0 0
$ bishop: num 0 0 1 1 0
以表格形式:
id type pawn rook knight bishop
1 1,2,3 1 1 1 0
2 2 0 1 0 0
3 2,3,4 0 1 1 1
4 4 0 0 0 1
5 1 1 0 0 0
[到目前为止,我尝试使用ex_df$type
将strsplit()
转换为具有数值的列表,然后将嵌套的lapply()
与dplyr的mutate()
与when_case()
结合使用,但这没有用。我在嵌套列表上遇到了麻烦,所以也许我的方法不正确?
我在发布之前进行了彻底的搜索,但感觉好像我在这里遗漏了一些非常明显的东西,例如一个我不知道的函数,正是它确实做到了这一点。也许我不是在寻找正确方向的解决方案?
我们可以使用cSplit_e
中的splitstackshape
在type
中创建逗号分隔值的二进制表示,然后更改列名。
output <- splitstackshape::cSplit_e(ex_df, "type", type = "character", fill = 0)
names(output)[-c(1, 2)] <- c('pawn', 'rook', 'knight', 'bishop')
output
# id type pawn rook knight bishop
#1 1 1,2,3 1 1 1 0
#2 2 2 0 1 0 0
#3 3 2,3,4 0 1 1 1
#4 4 4 0 0 0 1
#5 5 1 1 0 0 0
我们可以使用tidyverse
执行此操作
library(dplyr)
library(tidyr)
ex_df %>%
separate_rows(type, convert = TRUE) %>%
mutate(type = c('pawn', 'rook', 'knight', 'bishop')[type], n = 1) %>%
pivot_wider(names_from = type, values_from = n, values_fill = list(n = 0)) %>%
left_join(ex_df)%>%
select(names(ex_df), everything())
# id type pawn rook knight bishop
#1 1 1,2,3 1 1 1 0
#2 2 2 0 1 0 0
#3 3 2,3,4 0 1 1 1
#4 4 4 0 0 0 1
#5 5 1 1 0 0 0