У меня есть фрейм данных с категорическим переменным, содержащей списков строк, с переменной длиной (это важно, так как в противном случае этот вопрос будет дубликатом 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 разных подхода ниже. Я тестировал их с помощью system.time
на моем (Windows 7, 32 ГБ оперативной памяти) на базе данных реального, состоящий из 1М строк, каждая строка содержит список длиной от 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
Так что это подход, который я буду отмечать.
или 'data.frame (х = DF $ х, (sapply (DF $ у, функция (л) {таблица (фактор (л, уровни = ПИСЬМА [1: 5]))}))) ' – alistaire
@alistaire возможно' levels = unique (unlist (df $ y)) 'вместо' LETTERS [1: 5] '? – Sotos
@Sotos У меня это было, но понял, что это меньше вычислений. Лучший маршрут - сохранить это как отдельную переменную, но для этого потребуется вторая строка ... – alistaire