Question

J'ai une liste de dataframes pour laquelle je suis certain qu'ils contiennent tous au moins une ligne (en fait, certains contiennent qu'une seule ligne, et d'autres contiennent un nombre donné de lignes), et qu'ils ont tous les mêmes colonnes (noms et types).En cas de questions, je suis également certain qu'il n'y a pas de NA n'importe où dans les lignes.

La situation peut être simulé comme ceci:

#create one row
onerowdfr<-do.call(data.frame, c(list(), rnorm(100) , lapply(sample(letters[1:2], 100, replace=TRUE), function(x){factor(x, levels=letters[1:2])})))
colnames(onerowdfr)<-c(paste("cnt", 1:100, sep=""), paste("cat", 1:100, sep=""))
#reuse it in a list
someParts<-lapply(rbinom(200, 1, 14/200)*6+1, function(reps){onerowdfr[rep(1, reps),]})

J'ai mis les paramètres (de la randomisation), de sorte qu'ils approximative ma véritable situation.

Maintenant, je veux réunir tous ces dataframes dans un dataframe.J'ai pensé à l'aide de rbind ferait l'affaire, comme ceci:

system.time(
result<-do.call(rbind, someParts)
)

Maintenant, sur mon système (qui n'est pas particulièrement lent), et avec les paramètres ci-dessus, c'est la sortie du système.temps:

   user  system elapsed 
   5.61    0.00    5.62

Près de 6 secondes pour rbind-ing 254 (dans mon cas) les lignes de 200 variables?Sûrement, il y a un moyen d'améliorer la performance ici?Dans mon code, je dois faire des choses similaires très souvent (c'est à partir de l'imputation multiple), donc j'ai besoin de cela pour être aussi rapide que possible.

Était-ce utile?

La solution

Pouvez-vous construire votre matrices avec des variables numériques uniquement et convertir à un facteur à la fin? rbind est beaucoup plus rapide sur les numériques des matrices.

Sur mon système, à l'aide de trames de données:

> system.time(result<-do.call(rbind, someParts))
   user  system elapsed 
  2.628   0.000   2.636 

La construction de la liste avec tous numériques des matrices à la place:

onerowdfr2 <- matrix(as.numeric(onerowdfr), nrow=1)
someParts2<-lapply(rbinom(200, 1, 14/200)*6+1, 
                   function(reps){onerowdfr2[rep(1, reps),]})

résultats dans beaucoup plus vite rbind.

> system.time(result2<-do.call(rbind, someParts2))
   user  system elapsed 
  0.001   0.000   0.001

EDIT:Voici une autre possibilité;il combine chaque colonne à son tour.

> system.time({
+   n <- 1:ncol(someParts[[1]])
+   names(n) <- names(someParts[[1]])
+   result <- as.data.frame(lapply(n, function(i) 
+                           unlist(lapply(someParts, `[[`, i))))
+ })
   user  system elapsed 
  0.810   0.000   0.813  

Toujours pas presque aussi rapidement qu'à l'aide de matrices si.

EDIT 2:

Si vous n'avez que des nombres et des facteurs, il n'est pas difficile de convertir tout numérique, rbind eux, et de convertir les colonnes nécessaires arrière de facteurs.Cela suppose que tous les facteurs ont exactement les mêmes niveaux.La conversion d'un facteur par rapport à un nombre entier est également plus rapide que du numérique donc je me force à l'entier en premier.

someParts2 <- lapply(someParts, function(x)
                     matrix(unlist(x), ncol=ncol(x)))
result<-as.data.frame(do.call(rbind, someParts2))
a <- someParts[[1]]
f <- which(sapply(a, class)=="factor")
for(i in f) {
  lev <- levels(a[[i]])
  result[[i]] <- factor(as.integer(result[[i]]), levels=seq_along(lev), labels=lev)
}

La synchronisation de mon système:

   user  system elapsed 
   0.090    0.00    0.091 

Autres conseils

Not a huge boost, but swapping rbind for rbind.fill from the plyr package knocks about 10% off the running time (with the sample dataset, on my machine).

If you really want to manipulate your data.frames faster, I would suggest to use the package data.table and the function rbindlist(). I did not perform extensive tests but for my dataset (3000 dataframes, 1000 rows x 40 columns each) rbindlist() takes only 20 seconds.

This is ~25% faster, but there has to be a better way...

system.time({
  N <- do.call(sum, lapply(someParts, nrow))
  SP <- as.data.frame(lapply(someParts[[1]], function(x) rep(x,N)))
  k <- 0
  for(i in 1:length(someParts)) {
    j <- k+1
    k <- k + nrow(someParts[[i]])
    SP[j:k,] <- someParts[[i]]
  }
})

Make sure you're binding dataframe to dataframe. Ran into huge perf degradation when binding list to dataframe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top