J'ai une liste imbriquée de données. Sa longueur est de 132 et chaque élément est une liste de longueur 20. Existe-t-il un moyen rapide de convertir cette structure en un bloc de données qui comprend 132 lignes et 20 colonnes de données?
Voici quelques exemples de données avec lesquelles travailler:
l <- replicate(
132,
list(sample(letters, 20)),
simplify = FALSE
)
Réponses:
En supposant que votre liste de listes s'appelle
l
:Ce qui précède convertira toutes les colonnes de caractères en facteurs, pour éviter cela, vous pouvez ajouter un paramètre à l'appel data.frame ():
la source
Avec
rbind
Edit: retour
data.frame
delist
la version précédente de 's au lieu de vecteurs (comme l'a souligné @IanSudbery dans les commentaires).la source
rbind(your_list)
renvoie une matrice de liste 1x32?do.call
passe des éléments deyour_list
comme arguments àrbind
. C'est l'équivalent derbind(your_list[[1]], your_list[[2]], your_list[[3]], ....., your_list[[length of your_list]])
.your_list
contenir des vecteurs de taille égale.NULL
a une longueur de 0, il devrait donc échouer.Vous pouvez utiliser le
plyr
package. Par exemple, une liste imbriquée du formulairea maintenant une longueur de 4 et chaque liste
l
contient une autre liste de la longueur 3. Maintenant, vous pouvez exécuteret devrait obtenir le même résultat que dans la réponse @Marek et @nico.
la source
matrix
approche.data.frame(t(sapply(mylistlist,c)))
sapply
le convertit en matrice.data.frame
convertit la matrice en une trame de données.la source
c
de jouer ici, une instance des données de la liste? Oh attendez, c pour la fonction de concaténation non? Se confondre avec l'utilisation par @ mnel de c. Je suis également d'accord avec @dchandler, obtenir les bons noms de colonne était un besoin précieux dans mon cas d'utilisation. Solution brillante.?c
:Combine Values into a Vector or List
supposons que votre liste est appelée
L
,la source
data.frame(Reduce(rbind, list(c('col1','col2'))))
produit un bloc de données avec 2 lignes, 1 colonne (je m'attendais à 1 ligne 2 colonnes)Le paquet
data.table
a la fonctionrbindlist
qui est une implémentation ultra-rapide dedo.call(rbind, list(...))
.Il peut prendre une liste de
lists
,data.frames
oudata.tables
en entrée.Cela renvoie un
data.table
hérite dedata.frame
.Si vous voulez vraiment revenir à une utilisation data.frame
as.data.frame(DT)
la source
setDF
permet désormais de revenir à data.frame par référence.Le
tibble
package a une fonctionenframe()
qui résout ce problème en contraignant deslist
objets imbriqués à des objets imbriquéstibble
(trame de données "bien rangée"). Voici un bref exemple de R pour Data Science :Étant donné que vous avez plusieurs nids dans votre liste,
l
vous pouvez utiliser leunlist(recursive = FALSE)
pour supprimer l'imbrication inutile pour obtenir une seule liste hiérarchique, puis passer àenframe()
. J'utilisetidyr::unnest()
pour déloger la sortie dans un bloc de données "rangé" à un seul niveau, qui a vos deux colonnes (une pour le groupename
et une pour les observations avec les groupesvalue
). Si vous voulez des colonnes qui s'étendent, vous pouvez ajouter une colonne en utilisantadd_column()
qui répète simplement l'ordre des valeurs 132 fois. Ensuite, justespread()
les valeurs.la source
Selon la structure de vos listes, certaines
tidyverse
options fonctionnent bien avec des listes de longueurs inégales:Vous pouvez également mélanger des vecteurs et des trames de données:
la source
X2
ne peut pas être convertie d'un entier en caractèreReshape2 donne le même résultat que l'exemple plyr ci-dessus:
rendements:
Si vous n'aviez presque plus de pixels, vous pouvez tout faire en 1 ligne avec refonte ().
la source
Cette méthode utilise un
tidyverse
package ( purrr ).La liste:
Le convertir en un bloc de données (un
tibble
plus spécifiquement):la source
Étendre la réponse de @ Marek: si vous voulez éviter que les chaînes soient transformées en facteurs et que l'efficacité ne soit pas un problème, essayez
la source
Pour le cas général des listes profondément imbriquées avec 3 niveaux ou plus comme ceux obtenus à partir d'un JSON imbriqué:
considérez d'abord l'approche de
melt()
convertir la liste imbriquée dans un format grand:suivi par
dcast()
puis de nouveau large dans un ensemble de données bien rangé où chaque variable forme une colonne et chaque observation forme une ligne:la source
Plus de réponses, ainsi que des délais dans la réponse à cette question: Quelle est la façon la plus efficace de caster une liste en tant que bloc de données?
Le moyen le plus rapide, qui ne produit pas une trame de données avec des listes plutôt que des vecteurs pour les colonnes semble être (d'après la réponse de Martin Morgan):
la source
Parfois, vos données peuvent être une liste de listes de vecteurs de même longueur.
(Les vecteurs internes pourraient également être des listes, mais je simplifie pour faciliter la lecture).
Ensuite, vous pouvez apporter la modification suivante. N'oubliez pas que vous pouvez annuler la liste d'un niveau à la fois:
Utilisez maintenant votre méthode préférée mentionnée dans les autres réponses:
la source
C'est ce qui a finalement fonctionné pour moi:
do.call("rbind", lapply(S1, as.data.frame))
la source
la source
Pour une solution parallèle (multicœur, multisession, etc.) utilisant une
purrr
famille de solutions, utilisez:Où
l
est la liste.Pour comparer les plus efficaces,
plan()
vous pouvez utiliser:la source
La commande simple suivante a fonctionné pour moi:
Référence ( réponse Quora )
Mais cela échouera s'il n'est pas évident de convertir la liste en un bloc de données:
Remarque : La réponse est vers le titre de la question et peut ignorer certains détails de la question
la source
Un moyen court (mais peut-être pas le plus rapide) de le faire serait d'utiliser la base r, car une trame de données n'est qu'une liste de vecteurs de longueur égale . Ainsi, la conversion entre votre liste d'entrées et un data.frame 30 x 132 serait:
De là, nous pouvons le transposer dans une matrice de 132 x 30, et le reconvertir en une trame de données:
En une ligne:
Les noms d'utilisateur seront assez ennuyeux à regarder, mais vous pouvez toujours renommer ceux avec
rownames(new_df) <- 1:nrow(new_df)
la source
Que diriez-vous d'utiliser la
map_
fonction avec unefor
boucle? Voici ma solution:où
map_dfr
convertir chacun des éléments de la liste en un data.frame puisrbind
complètement.Dans votre cas, je suppose que ce serait:
la source