435 votes

Conversion d’une liste de trames de données dans une structure de données en R

J'ai un code qui à un endroit se termine avec une liste de trames de données qui j'ai vraiment envie de les convertir vers un seul gros bloc de données.

J'ai eu quelques conseils d'une question antérieure qui était en train de faire quelque chose de similaire mais plus complexe.

Voici un exemple de ce que je suis (c'est extrêmement simplifié pour l'illustration):

listOfDataFrames <- NULL

for (i in 1:100) {
    listOfDataFrames[[i]] <- data.frame(a=sample(letters, 500, rep=T),
                             b=rnorm(500), c=rnorm(500))
}

Je suis actuellement en utilisant ceci:

  df <- do.call("rbind", listOfDataFrames)

*EDIT*

oups. Dans ma hâte de mettre en application ce que j'avais "appris" dans une précédente question, j'ai totalement foiré. Oui, l' unlist() est tout simplement faux. Je suis en train de monter que de la question ci-dessus.

192voto

Shane Points 40885

Une autre option est d'utiliser un plyr fonction:

df <- ldply(listOfDataFrames, data.frame)

C'est un peu plus lent que l'original:

> system.time({ df <- do.call("rbind", listOfDataFrames) })
   user  system elapsed 
   0.25    0.00    0.25 
> system.time({ df2 <- ldply(listOfDataFrames, data.frame) })
   user  system elapsed 
   0.30    0.00    0.29
> identical(df, df2)
[1] TRUE

Ma conjecture est que l'utilisation d' do.call("rbind", ...) va être le plus rapide de l'approche que vous allez trouver, sauf si vous pouvez faire quelque chose comme (a) utiliser une des matrices à la place d'une base de données.images et (b) préallouer la finale de la matrice, et de confier à elle plutôt que de la développer.

Edit 1:

Basé sur Hadley commentaire, voici la dernière version de rbind.fill de CRAN:

> system.time({ df3 <- rbind.fill(listOfDataFrames) })
   user  system elapsed 
   0.24    0.00    0.23 
> identical(df, df3)
[1] TRUE

C'est plus facile que rbind, et légèrement plus rapide (ces horaires hold up sur plusieurs pistes). Et comme je le comprends, la version de plyr sur github est encore plus rapide que cela.

130voto

andrekos Points 543

Dans le but d'exhaustivité, je pensais que la réponse à cette question nécessite une mise à jour. "J'imagine qu'à l'aide de le faire.call("rbind", ...) va être le plus rapide de l'approche que vous trouverez..." C'est probablement vrai pour le mois de Mai 2010 et après un certain temps, mais dans environ sept 2011 une nouvelle fonction rbindlist() a été introduit dans les données.tableau package de la version 1.8.2, avec une remarque que "Cela fait la même chose à faire.call("rbind",l), mais beaucoup plus rapide". Comment beaucoup plus rapide?

library(benchmark)
benchmark(
  do.call = do.call("rbind", listOfDataFrames),
  plyr_rbind.fill = plyr::rbind.fill(listOfDataFrames), 
  plyr_ldply = plyr::ldply(listOfDataFrames, data.frame),
  data.table_rbindlist = as.data.frame(data.table::rbindlist(listOfDataFrames)),
  replications = 100, order = "relative", 
  columns=c('test','replications', 'elapsed','relative')
  ) 

                  test replications elapsed relative
4 data.table_rbindlist          100    0.11    1.000
1              do.call          100    9.39   85.364
2      plyr_rbind.fill          100   12.08  109.818
3           plyr_ldply          100   15.14  137.636

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