Jest usunięte odpowiedź tutaj, który wskazuje, że „splitstackshape” mogą być wykorzystane do tego . Może, ale usunięta odpowiedź wykorzystała złą funkcję. Zamiast tego powinien użyć funkcji listCol_w
. Niestety, w swojej obecnej postaci funkcja ta nie jest wektoryzowana między kolumnami, więc musisz zagnieżdżać wywołania do listCol_w
dla każdej kolumny, która wymaga spłaszczenia.
Oto podejście:
library(splitstackshape)
listCol_w(listCol_w(df, "COUNT", fill = NA), "TREAT", fill = NA)
## CAT COUNT_fl_1 COUNT_fl_2 COUNT_fl_3 TREAT_fl_1 TREAT_fl_2 TREAT_fl_3
## 1: A 1 2 3 Treat-a Treat-b NA
## 2: B 4 5 NA Treat-c Treat-d Treat-e
Zauważ, że fill = NA
została określona, ponieważ domyślnie fill = NA_character_
, które w przeciwnym razie byłyby przymuszania wszystkie wartości do charakteru.
Inną alternatywą byłoby użycie transpose
z "data.table". Oto możliwa implementacja (wygląda przerażająco, ale korzystanie z tej funkcji jest łatwe). Korzyści są następujące: (1) możesz określić kolumny do spłaszczenia, (2) możesz zdecydować, czy chcesz upuścić oryginalną kolumnę, czy nie, i (3) jest ona szybka.
flatten <- function(indt, cols, drop = FALSE) {
require(data.table)
if (!is.data.table(indt)) indt <- as.data.table(indt)
x <- unlist(indt[, lapply(.SD, function(x) max(lengths(x))), .SDcols = cols])
nams <- paste(rep(cols, x), sequence(x), sep = "_")
indt[, (nams) := unlist(lapply(.SD, transpose), recursive = FALSE), .SDcols = cols]
if (isTRUE(drop)) {
indt[, (nams) := unlist(lapply(.SD, transpose), recursive = FALSE),
.SDcols = cols][, (cols) := NULL]
}
indt[]
}
Użycie byłoby ...
Keeping oryginalne kolumny:
flatten(df, c("COUNT", "TREAT"))
# CAT COUNT TREAT COUNT_1 COUNT_2 COUNT_3 TREAT_1 TREAT_2 TREAT_3
# 1: A 1,2,3 Treat-a,Treat-b 1 2 3 Treat-a Treat-b NA
# 2: B 4,5 Treat-c,Treat-d,Treat-e 4 5 NA Treat-c Treat-d Treat-e
Dropping oryginalne kolumny:
flatten(df, c("COUNT", "TREAT"), TRUE)
# CAT COUNT_1 COUNT_2 COUNT_3 TREAT_1 TREAT_2 TREAT_3
# 1: A 1 2 3 Treat-a Treat-b NA
# 2: B 4 5 NA Treat-c Treat-d Treat-e
Zobacz this gist dla porównania z innymi proponowanymi rozwiązaniami.
Jak duże są twoje "prawdziwe" dane (czy wydajność jest problemem?) – Heroka
cSplit() z pakietu splitstackshape byłby dobrym rozwiązaniem. – jazzurro
Na twoim przykładzie 'df [2: 3] <- lapply (df [, 2: 3], function (x) do.call (rbind, lapply (x," [", 1: 3))) wydaje się być fajny początek. – nicola