我有来自一项调查的多项选择问题的数据。该列包含以逗号分隔的字符串形式的值。我的数据框如下所示:
ID Var
1 1 3,12,14,15,16,18,20,21
2 2 3,14,20
3 3 3,14,16
4 4 3,12
5 5 3,6,14,15,17,20
我想将这些值拆分到各自的列中,例如第 1 列中的 1、第 2 列中的 2 等。总共有 21 个值。
我尝试使用
str_split_fixed
,它按照值出现的顺序将值分成几列:
str_split_fixed(df$Var, ",", 21)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,] "3" "12" "14" "15" "16" "18" "20" "21" "" "" "" "" "" ""
[2,] "3" "14" "20" "" "" "" "" "" "" "" "" "" "" ""
[3,] "3" "14" "16" "" "" "" "" "" "" "" "" "" "" ""
[4,] "3" "12" "" "" "" "" "" "" "" "" "" "" "" ""
[5,] "3" "6" "14" "15" "17" "20" "" "" "" "" "" "" "" ""
我也尝试过使用
cSplit
产生了类似的东西:
cSplit(df, "Var", ",")
ID Var_01 Var_02 Var_03 Var_04 Var_05 Var_06 Var_07 Var_08 Var_09...
1 3 12 14 15 16 18 20 21 NA
2 3 14 20 NA NA NA NA NA NA
3 3 14 16 NA NA NA NA NA NA
4 3 12 NA NA NA NA NA NA NA
5 3 6 14 15 17 20 NA NA NA
我想制作这样的东西:
ID Var_01 Var_02 Var_03 Var_04 Var_05 Var_06 Var_07 Var_08 Var_09...
1 NA NA 3 NA NA NA NA NA NA
2 NA NA 3 NA NA NA NA NA NA
3 NA NA 3 NA NA NA NA NA NA
4 NA NA 3 NA NA NA NA NA NA
5 NA NA 3 NA NA 6 NA NA NA
我仍在研究 R,所以任何指点将不胜感激。谢谢!
V <- strsplit(df$Var, ",") |> lapply(as.integer)
V2 <- cbind(rep(seq_along(V), times = lengths(V)), unlist(V))
m <- data.frame(matrix(NA, nrow = nrow(df), ncol = max(unlist(V))))
colnames(m) <- sprintf("Var_%02d", 1:max(unlist(V)))
m[V2] <- V2[,2]
cbind(df, m)
# ID Var Var_01 Var_02 Var_03 Var_04 Var_05 Var_06 Var_07 Var_08 Var_09 Var_10 Var_11 Var_12 Var_13 Var_14 Var_15 Var_16 Var_17 Var_18 Var_19 Var_20 Var_21
# 1 1 3,12,14,15,16,18,20,21 NA NA 3 NA NA NA NA NA NA NA NA 12 NA 14 15 16 NA 18 NA 20 21
# 2 2 3,14,20 NA NA 3 NA NA NA NA NA NA NA NA NA NA 14 NA NA NA NA NA 20 NA
# 3 3 3,14,16 NA NA 3 NA NA NA NA NA NA NA NA NA NA 14 NA 16 NA NA NA NA NA
# 4 4 3,12 NA NA 3 NA NA NA NA NA NA NA NA 12 NA NA NA NA NA NA NA NA NA
# 5 5 3,6,14,15,17,20 NA NA 3 NA NA 6 NA NA NA NA NA NA NA 14 15 NA 17 NA NA 20 NA
[
索引(对于矩阵和框架)接受 row,column
索引的 2 列矩阵进行提取和赋值,这就是我们对 m[V2]
所做的事情。
据我所知,这并不是一个非常常见的转变。你可以写一个辅助函数,比如
split_index <- function(x) {
rows <- lapply(strsplit(x, ","), as.numeric)
N <- max(unlist(rows))
vals <- lapply(rows, function(v) {
r <- numeric(N)
r[v] <- as.character(v)
r
})
vals
}
你可以这样称呼它
split_index(df$Var)
或者如果你想组合成一个矩阵
split_index(df$Var) |> do.call(rbind, args=_)
使用两个外部包:
library(data.table)
library(stringi)
ncolumns <- max(stri_count_fixed(df$Var, ",")) + 1
df[sprintf("var%s", seq_len(ncolumns))] <- tstrsplit(df$Var, ",")
# id Var var1 var2 var3 var4 var5 var6 var7 var8
# 1 1 3,12,14,15,16,18,20,21 3 12 14 15 16 18 20 21
# 2 2 3,14,20 3 14 20 <NA> <NA> <NA> <NA> <NA>
# 3 3 3,14,16 3 14 16 <NA> <NA> <NA> <NA> <NA>
# 4 4 3,12 3 12 <NA> <NA> <NA> <NA> <NA> <NA>
# 5 5 3,6,14,15,17,20 3 6 14 15 17 20 <NA> <NA>
可重复的数据
df <- data.frame(
id = 1:5,
Var = c("3,12,14,15,16,18,20,21", "3,14,20", "3,14,16", "3,12", "3,6,14,15,17,20")
)