C'è una risposta cancellato qui che indica che "splitstackshape" potrebbe essere utilizzato per questo . Può, ma la risposta cancellata ha usato la funzione sbagliata. Invece, dovrebbe utilizzare la funzione listCol_w
. Sfortunatamente, nella sua forma attuale, questa funzione non è vettorizzata su colonne, quindi è necessario nidificare le chiamate a listCol_w
per ogni colonna che deve essere appiattita.
Ecco il metodo:
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
Nota che fill = NA
è stato specificato perchè default fill = NA_character_
, che altrimenti costringere tutti i valori a carattere.
Un'altra alternativa sarebbe quella di utilizzare transpose
da "data.table". Ecco una possibile implementazione (sembra spaventoso, ma l'utilizzo della funzione è semplice). I vantaggi sono che (1) è possibile specificare le colonne da appiattire, (2) è possibile decidere se si desidera eliminare la colonna originale o meno, e (3) è veloce.
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[]
}
L'utilizzo sarebbe ...
Mantenere colonne originali:
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
eliminazione di colonne originali:
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
Vedi this gist per un confronto con le altre soluzioni proposte.
Quanto sono grandi i dati "reali" (le prestazioni sono un problema?) – Heroka
cSplit() dal pacchetto splitstackshape sarebbe una buona opzione. – jazzurro
Con il tuo esempio 'df [2: 3] <- lapply (df [, 2: 3], function (x) do.call (rbind, lapply (x," [", 1: 3))) sembra un buon inizio – nicola