@GioraSimchoni как это работает?
я есть фрейм данных с категориальной переменной, содержащейсписки строк, с переменной длиной (это важно, потому что в противном случае этот вопрос был бы дубликатомэтот или жеэтот), например:
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 различных подхода ниже. Я проверил их, используяsystem.time
на моем (Windows 7, 32 ГБ ОЗУ) ноутбуке нареальный набор данных, состоящий из 1M строк, каждая строка содержит список длиной от 1 до 4 строк (из ~ 350 уникальных значений строк), всего 200 МБ на диске. Таким образом, ожидаемый результат - это фрейм данных с размерами 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
Так что этот подход я отмечу как принятый.