J'ai un data.frame que je voudrais convertir en une liste par lignes, ce qui signifie que chaque ligne correspondrait à ses propres éléments de liste. En d'autres termes, je voudrais une liste qui est aussi longue que le data.frame a des lignes.
Jusqu'à présent, j'ai abordé ce problème de la manière suivante, mais je me demandais s'il y avait une meilleure façon d'aborder cela.
xy.df <- data.frame(x = runif(10), y = runif(10))
# pre-allocate a list and fill it with a loop
xy.list <- vector("list", nrow(xy.df))
for (i in 1:nrow(xy.df)) {
xy.list[[i]] <- xy.df[i,]
}
split
chaque élément a un typedata.frame with 1 rows and N columns
au lieu delist of length N
split
vous devriez probablement le fairedrop=T
sinon vos niveaux d'origine pour les facteurs ne baisseront pasEureka!
la source
unlist(apply(xy.df, 1, list), recursive = FALSE)
. Cependant, la solution de flodel est la plus efficace que d'utiliserapply
out
.t
convertit ledata.fame
en a dematrix
sorte que les éléments de votre liste soient des vecteurs atomiques, et non une liste comme l'OP demandé. Ce n'est généralement pas un problème jusqu'à ce que votrexy.df
contienne des types mixtes ...apply
. C'est en fait juste une boucle for implémentée dans R.lapply
effectue la boucle en C, ce qui est beaucoup plus rapide. Ce format de liste de lignes est en fait préférable si vous faites beaucoup de boucles.apply
version est.mapply(data.frame, xy.df, NULL)
Si vous voulez abuser complètement du data.frame (comme je le fais) et que vous aimez garder la fonctionnalité $, une façon est de diviser votre data.frame en data.frames sur une ligne rassemblés dans une liste:
Ce n'est pas seulement de la masturbation intellectuelle, mais permet de `` transformer '' le data.frame en une liste de ses lignes, en gardant l'indexation $ qui peut être utile pour une utilisation ultérieure avec lapply (en supposant que la fonction que vous passez à lapply utilise cette $ indexation)
la source
data.frame
s en un seuldata.frame
?Une solution plus moderne utilise uniquement
purrr::transpose
:la source
Je travaillais là-dessus aujourd'hui pour un data.frame (vraiment un data.table) avec des millions d'observations et 35 colonnes. Mon objectif était de renvoyer une liste de data.frames (data.tables) chacun avec une seule ligne. Autrement dit, je voulais diviser chaque ligne en un data.frame séparé et les stocker dans une liste.
Voici deux méthodes que j'ai proposées qui étaient environ 3 fois plus rapides que
split(dat, seq_len(nrow(dat)))
pour cet ensemble de données. Ci-dessous, je compare les trois méthodes sur un ensemble de données de 7500 lignes et 5 colonnes ( iris répété 50 fois).Cela renvoie
Bien que les différences ne soient pas aussi importantes que dans mon test précédent, la
setDF
méthode directe est nettement plus rapide à tous les niveaux de la distribution des exécutions avec max (setDF) <min (split) et laattr
méthode est généralement plus de deux fois plus rapide.Une quatrième méthode est le champion extrême, qui est un simple imbriqué
lapply
, renvoyant une liste imbriquée. Cette méthode illustre le coût de construction d'un data.frame à partir d'une liste. De plus, toutes les méthodes que j'ai essayées avec ladata.frame
fonction étaient à peu près un ordre de grandeur plus lentes que lesdata.table
techniques.Les données
la source
Semble qu'une version actuelle du
purrr
package (0.2.2) est la solution la plus rapide:Comparons les solutions les plus intéressantes:
Résultats:
Nous pouvons également obtenir le même résultat avec
Rcpp
:Maintenant, comparez avec
purrr
:Résultats:
la source
by_row()
est maintenant passé àlibrary(purrrlyr)
Quelques options supplémentaires:
Avec
asplit
Avec
split
etrow
Les données
la source
Le meilleur moyen pour moi était:
Exemple de données:
Nous appelons la
BBmisc
bibliothèqueEt le résultat sera:
la source
Une autre manière est de convertir le df en matrice, puis d'appliquer la
lappy
fonction list apply dessus:ldf <- lapply(as.matrix(myDF), function(x)x)
la source
Une autre alternative utilisant
library(purrr)
(qui semble être un peu plus rapide sur les gros data.frames)la source
Comme @flodel l'a écrit: Cela convertit votre dataframe en une liste qui a le même nombre d'éléments que le nombre de lignes dans dataframe:
Vous pouvez en outre ajouter une fonction pour sélectionner uniquement les colonnes qui ne sont pas NA dans chaque élément de la liste:
la source
La
by_row
fonction dupurrrlyr
package le fera pour vous.Cet exemple montre
Par défaut, la valeur renvoyée par
myfn
est placée dans une nouvelle colonne de liste dans le df appelé.out
. Le$.out
à la fin de l'instruction ci-dessus sélectionne immédiatement cette colonne, renvoyant une liste de listes.la source