【发布时间】:2017-05-31 01:36:01
【问题描述】:
我有一个数据框,其中包含一个分类变量,其中包含 lists 的字符串,长度可变(这很重要,否则这个问题将与 this 或 this 重复),例如:
df <- data.frame(x = 1:5)
df$y <- list("A", c("A", "B"), "C", c("B", "D", "C"), "E")
df
x y 1 1 A 2 2 A, B 3 3 C 4 4 B, D, C 5 5 E
对于在df$y 中任何地方看到的每个唯一字符串,所需的形式是一个虚拟变量,即:
data.frame(x = 1:5, A = c(1,1,0,0,0), B = c(0,1,0,1,0), C = c(0,0,1,1,0), D = c(0,0,0,1,0), E = c(0,0,0,0,1))
x A B C D E 1 1 1 0 0 0 0 2 2 1 1 0 0 0 3 3 0 0 1 0 0 4 4 0 1 1 1 0 5 5 0 0 0 0 1
这种幼稚的方法有效:
> uniqueStrings <- unique(unlist(df$y))
> n <- ncol(df)
> for (i in 1:length(uniqueStrings)) {
+ df[, n + i] <- sapply(df$y, function(x) ifelse(uniqueStrings[i] %in% x, 1, 0))
+ colnames(df)[n + i] <- uniqueStrings[i]
+ }
但是对于大数据帧来说,它是非常丑陋、懒惰和缓慢的。
有什么建议吗? tidyverse 有什么花哨的吗?
更新:我在下面得到了 3 种不同的方法。我在我的(Windows 7,32GB RAM)笔记本电脑上使用system.time 对它们进行了测试,该数据集包含 1M 行,每行包含长度为 1 到 4 个字符串的列表(约 350唯一的字符串值),磁盘上总共有 200MB。所以预期的结果是一个尺寸为 1M x 350 的数据框。tidyverse (@Sotos) 和 base (@joel.wilson) 方法花了很长时间,我不得不重新启动 R。qdapTools (@akrun)然而,这种方法效果很好:
> system.time(res1 <- mtabulate(varsLists))
user system elapsed
47.05 10.27 116.82
所以这是我将标记为接受的方法。
【问题讨论】:
-
或
data.frame(x = df$x, t(sapply(df$y, function(l){table(factor(l, levels = LETTERS[1:5]))}))) -
@alistaire 也许是
levels = unique(unlist(df$y))而不是LETTERS[1:5]? -
@Sotos 我有,但认为这是更少的计算。最好的方法是将其存储为单独的变量,但这需要第二行...
-
@alistaire True
标签: r list dummy-variable tidyverse