我有一个分类变量保持列表字符串,具有可变长度的数据帧的虚拟变量(这是很重要的,否则这个问题将是this重复或this),例如:R:创建一个基于列表的分类变量*
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
在real数据集上测试了这些数据集,其中包含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,功能(l){表(因子(1,级别= LETTERS [1:5] ))})))' – alistaire
@alistaire maybe'levels = unique(unlist(df $ y))''而不是'LETTERS [1:5]'? – Sotos
@Sotos我有,但认为这是更少的计算。最好的办法是把它作为一个单独的变量存储,但这需要第二行... – alistaire