web-dev-qa-db-fra.com

Comment convertir une énorme liste de vecteurs en matrice plus efficacement dans R?

J'ai une liste de longueur 130 000 où chaque élément est un vecteur de caractère de longueur 110. J'aimerais convertir cette liste en matrice de dimension 1 430 000 * 10. Comment puis-je le faire plus efficacement? Mon code est:

output=NULL
for(i in 1:length(z)) output=rbind(output,matrix(z[[i]],ncol=10,byrow=T))
57
user1787675

Cela devrait être équivalent à votre code actuel, mais beaucoup plus rapidement:

output <- matrix(unlist(z), ncol = 10, byrow = TRUE)
118
flodel

Je pense tu veux

output <- do.call(rbind,lapply(z,matrix,ncol=10,byrow=TRUE))

c'est-à-dire en combinant l'utilisation de do.call(rbind,...) par @ BlueMagister avec une instruction lapply pour convertir les éléments de liste individuels en matrices 11 * 10 ...

Points de repère (la solution unlist de @ flodel est 5 fois plus rapide que la mienne et 230 fois plus rapide que la méthode d'origine ...)

n <- 1000
z <- replicate(n,matrix(1:110,ncol=10,byrow=TRUE),simplify=FALSE)
library(rbenchmark)
origfn <- function(z) {
    output <- NULL 
    for(i in 1:length(z))
        output<- rbind(output,matrix(z[[i]],ncol=10,byrow=TRUE))
}
rbindfn <- function(z) do.call(rbind,lapply(z,matrix,ncol=10,byrow=TRUE))
unlistfn <- function(z) matrix(unlist(z), ncol = 10, byrow = TRUE)

##          test replications elapsed relative user.self sys.self 
## 1   origfn(z)          100  36.467  230.804    34.834    1.540  
## 2  rbindfn(z)          100   0.713    4.513     0.708    0.012 
## 3 unlistfn(z)          100   0.158    1.000     0.144    0.008 

Si cela s’adapte correctement (c’est-à-dire que vous ne rencontrez pas de problème de mémoire), le problème complet prend environ 130 * 0,2 secondes = 26 secondes sur une machine comparable (je l’ai fait sur un MacBook Pro âgé de 2 ans).

15
Ben Bolker

Il serait utile d'avoir des exemples d'informations sur votre production. Utiliser récursivement rbind sur des objets de plus en plus gros est non recommandé. Ma première hypothèse sur quelque chose qui pourrait vous aider:

z <- list(1:3,4:6,7:9)
do.call(rbind,z)

Voir une question connexe pour plus d’efficacité, si nécessaire.

5
Blue Magister

Vous pouvez aussi utiliser,

output <- as.matrix(as.data.frame(z))

L'utilisation de la mémoire est très similaire à

output <- matrix(unlist(z), ncol = 10, byrow = TRUE)

Ce qui peut être vérifié avec mem_changed() à partir de library(pryr).

0
csta