Transformer une liste de listes en dataframe
J'ai une liste contenant un certain nombre d'autres listes, chacune contenant des nombres variables de vecteurs de caractères, avec des nombres variables d'éléments. Je veux créer un dataframe où chaque liste serait représentée sous forme de ligne et chaque vecteur de caractère dans cette liste serait une colonne. Là où le vecteur de caractères a> 1 élément, les éléments seraient concaténés et séparés en utilisant un signe "+", de sorte qu'ils puissent être stockés comme une chaîne. Les données ressemblent à ceci:
fruits <- list(
list(c("orange"), c("pear")),
list(c("pear", "orange")),
list(c("lemon", "apple"),
c("pear"),
c("grape"),
c("apple"))
)
La sortie attendue est comme ceci:
fruits_df <- data.frame(col1 = c("orange", "pear + orange", "lemon + apple"),
col2 = c("pear", NA, "pear"),
col3 = c(NA, NA, "grape"),
col4 = c(NA, NA, "apple"))
Il n'y a pas de limite au nombre de vecteurs de caractères pouvant être contenus dans une liste, la solution doit donc créer dynamiquement des colonnes, conduisant à un df où le nombre de colonnes est égal à la longueur de la liste contenant le plus grand nombre de caractères vecteurs.
Réponses
Pour chaque liste dans, fruitsvous pouvez créer un dataframe d'une ligne et lier les données.
dplyr::bind_rows(lapply(fruits, function(x) as.data.frame(t(sapply(x,
function(y) paste0(y, collapse = "+"))))))
# V1 V2 V3 V4
#1 orange pear <NA> <NA>
#2 pear+orange <NA> <NA> <NA>
#3 lemon+apple pear grape apple
C'est un peu brouillon mais voici un moyen
cols <- lapply(fruits, function(x) sapply(x, paste, collapse=" + "))
ncols <- max(lengths(cols))
dd <- do.call("rbind.data.frame", lapply(cols, function(x) {length(x) <- ncols; x}))
names(dd) <- paste0("col", 1:ncol(dd))
dd
# col1 col2 col3 col4
# 1 orange pear <NA> <NA>
# 2 pear + orange <NA> <NA> <NA>
# 3 lemon + apple pear grape apple
ou une autre stratégie
ncols <- max(lengths(fruits))
dd <- data.frame(lapply(seq.int(ncols), function(x) sapply(fruits, function(y) paste(unlist(y[x]), collapse=" + "))))
names(dd) <- paste0("col", 1:ncols)
dd
Mais en réalité, vous devez créer chaque colonne ou ligne de votre liste, puis les combiner.
Une autre approche qui fusionne la liste en un data.frame en utilisant rrapply::rrapply, puis la convertit au format requis en utilisant data.table::dcast:
library(rrapply)
library(data.table)
## melt to long data.frame
long <- rrapply(fruits, f = paste, how = "melt", collapse = " + ")
## cast to wide data.table
setDT(long)
dcast(long[, .(L1, L2, value = unlist(value))], L1 ~ L2)[, !"L1"]
#> ..1 ..2 ..3 ..4
#> 1: orange pear <NA> <NA>
#> 2: pear + orange <NA> <NA> <NA>
#> 3: lemon + apple pear grape apple