642 votes

Convertir une liste en un cadre de données

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 rapide comment convertir cette structure en un cadre de données comportant 132 lignes et 20 colonnes de données ?

Voici quelques exemples de données avec lesquelles vous pouvez travailler :

l <- replicate(
  132,
  as.list(sample(letters, 20)),
  simplify = FALSE
)

2 votes

Vous voulez donc que chaque élément de la liste soit une ligne de données dans votre data.frame ?

2 votes

@RichieCotton Ce n'est pas le bon exemple. "chaque élément est un liste de longueur 20" et vous obtenez chaque élément est une liste à un élément de vecteur de longueur 20.

1 votes

J'arrive tard à la fête, mais je n'ai vu personne mentionner este Ce que j'ai trouvé très pratique (pour ce que je cherchais à faire).

614voto

Marek Points 18000

Con rbind

do.call(rbind.data.frame, your_list)

Edit : Retour de la version précédente data.frame de list au lieu de vecteurs (comme @IanSudbery l'a fait remarquer dans les commentaires).

7 votes

Pourquoi cela fonctionne-t-il mais rbind(your_list) retourne une matrice de liste 1x32 ?

36 votes

@eykanal do.call passer des éléments de your_list comme arguments à rbind . C'est l'équivalent de rbind(your_list[[1]], your_list[[2]], your_list[[3]], ....., your_list[[length of your_list]]) .

2 votes

Cette méthode souffre de la situation nulle.

480voto

nico Points 21115

Mise à jour en juillet 2020 :

La valeur par défaut du paramètre stringsAsFactors est maintenant default.stringsAsFactors() ce qui donne FALSE par défaut.


En supposant que votre liste de listes s'appelle l :

df <- data.frame(matrix(unlist(l), nrow=length(l), byrow=TRUE))

La méthode ci-dessus convertira toutes les colonnes de caractères en facteurs. Pour éviter cela, vous pouvez ajouter un paramètre à l'appel data.frame() :

df <- data.frame(matrix(unlist(l), nrow=132, byrow=TRUE),stringsAsFactors=FALSE)

132 votes

Attention ici si vos données ne sont pas toutes du même type. Le passage par une matrice signifie que toutes les données seront converties en un type commun. Par exemple, si vous avez une colonne de données en caractères et une colonne de données numériques, les données numériques seront converties en chaînes de caractères par matrix() et ensuite en facteurs par data.frame().

1 votes

Quelle est la meilleure façon de procéder lorsque la liste comporte des valeurs manquantes, ou d'inclure NA dans le cadre de données ?

0 votes

@Dave : Je ne pense pas vous suivre... cela fonctionne même s'il y a des NAs autour...

163voto

mropa Points 2813

Vous pouvez utiliser le plyr paquet. Par exemple, une liste imbriquée de la forme

l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
      , b = list(var.1 = 4, var.2 = 5, var.3 = 6)
      , c = list(var.1 = 7, var.2 = 8, var.3 = 9)
      , d = list(var.1 = 10, var.2 = 11, var.3 = 12)
      )

a maintenant une longueur de 4 et chaque liste dans l contient une autre liste de longueur 3. Vous pouvez maintenant exécuter

  library (plyr)
  df <- ldply (l, data.frame)

et vous devriez obtenir le même résultat que dans la réponse @Marek et @nico.

8 votes

Excellente réponse. Pourriez-vous m'expliquer un peu comment cela fonctionne ? Il renvoie simplement un cadre de données pour chaque entrée de la liste ?

14 votes

Je pense que c'est la MEILLEURE réponse. Elle renvoie un data.frame honnête. Tous les types de données (caractère, numérique, etc.) sont correctement transformés. Si la liste a différents types de données, ils seront tous transformés en caractères avec la commande matrix approche.

1 votes

L'échantillon fourni ici n'est pas celui fourni par la question. le résultat de cette réponse sur l'ensemble de données original est incorrect.

135voto

Alex Brown Points 15776

Correction de l'échantillon de données pour qu'il corresponde à la description originale "chaque élément est une liste de longueur 20".

mylistlist <- replicate(
  132,
  as.list(sample(letters, 20)),
  simplify = FALSE
)

nous pouvons le convertir en un cadre de données comme ceci :

data.frame(t(sapply(mylistlist,c)))

sapply le convertit en une matrice. data.frame convertit la matrice en un cadre de données.

résultant en :

enter image description here

22 votes

La meilleure réponse de loin ! Aucune des autres solutions ne corrige les types et les noms de colonnes. MERCI !

2 votes

Quel rôle souhaitez-vous jouer ? c à jouer ici, une instance des données de la liste ? Oh, attendez, c pour la fonction concaténation, c'est ça ? Je m'embrouille avec l'utilisation de c par @mnel. Je suis également d'accord avec @dchandler, obtenir les noms de colonnes corrects était un besoin important dans mon cas d'utilisation. Solution brillante.

0 votes

Ce droit - fonction c standard ; de ?c : Combine Values into a Vector or List

70voto

mnel Points 48160

Le paquet data.table a la fonction rbindlist qui est une implémentation super rapide de do.call(rbind, list(...)) .

Il peut prendre une liste de lists , data.frames o data.tables comme entrée.

library(data.table)
ll <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
  , b = list(var.1 = 4, var.2 = 5, var.3 = 6)
  , c = list(var.1 = 7, var.2 = 8, var.3 = 9)
  , d = list(var.1 = 10, var.2 = 11, var.3 = 12)
  )

DT <- rbindlist(ll)

Cela renvoie un data.table hérite de data.frame .

Si vous vraiment vous voulez reconvertir en data.frame utilisez as.data.frame(DT)

1 votes

Concernant la dernière ligne, setDF permet maintenant de retourner à data.frame par référence.

1 votes

Pour ma liste de 30 000 éléments, rbindlist a fonctionné beaucoup plus rapidement que ldply.

0 votes

C'est en effet super rapide !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X