Comment créer une matrice à partir d'une liste de vecteurs dans R?

102

Objectif: à partir d'une liste de vecteurs d'égale longueur, créer une matrice où chaque vecteur devient une ligne.

Exemple:

> a <- list()
> for (i in 1:10) a[[i]] <- c(i,1:5)
> a
[[1]]
[1] 1 1 2 3 4 5

[[2]]
[1] 2 1 2 3 4 5

[[3]]
[1] 3 1 2 3 4 5

[[4]]
[1] 4 1 2 3 4 5

[[5]]
[1] 5 1 2 3 4 5

[[6]]
[1] 6 1 2 3 4 5

[[7]]
[1] 7 1 2 3 4 5

[[8]]
[1] 8 1 2 3 4 5

[[9]]
[1] 9 1 2 3 4 5

[[10]]
[1] 10  1  2  3  4  5

Je voudrais:

      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    1    1    2    3    4    5
 [2,]    2    1    2    3    4    5
 [3,]    3    1    2    3    4    5
 [4,]    4    1    2    3    4    5
 [5,]    5    1    2    3    4    5
 [6,]    6    1    2    3    4    5
 [7,]    7    1    2    3    4    5
 [8,]    8    1    2    3    4    5
 [9,]    9    1    2    3    4    5
[10,]   10    1    2    3    4    5 
Christophe DuBois
la source

Réponses:

124

Une option consiste à utiliser do.call():

 > do.call(rbind, a)
      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    1    1    2    3    4    5
 [2,]    2    1    2    3    4    5
 [3,]    3    1    2    3    4    5
 [4,]    4    1    2    3    4    5
 [5,]    5    1    2    3    4    5
 [6,]    6    1    2    3    4    5
 [7,]    7    1    2    3    4    5
 [8,]    8    1    2    3    4    5
 [9,]    9    1    2    3    4    5
[10,]   10    1    2    3    4    5
Christophe DuBois
la source
5
Donc, la différence entre ceci et le standard rbind () est que do.call () passe chaque élément de la liste comme un argument distinct - est-ce vrai? do.call (rbind, a) est équivalent à rbind (a [[1]], a [[2]] ... a [[10]])?
Matt Parker
5
do.call () est idéal pour cela, j'aurais aimé qu'il soit mieux "documenté" dans les documents d'introduction.
andrewj
16

simplify2arrayest une fonction de base assez intuitive. Cependant, étant donné que la valeur par défaut de R est de remplir d'abord les données par colonnes, vous devrez transposer la sortie. ( sapplyutilise simplify2array, tel que documenté dans help(sapply).)

> t(simplify2array(a))
      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    1    1    2    3    4    5
 [2,]    2    1    2    3    4    5
 [3,]    3    1    2    3    4    5
 [4,]    4    1    2    3    4    5
 [5,]    5    1    2    3    4    5
 [6,]    6    1    2    3    4    5
 [7,]    7    1    2    3    4    5
 [8,]    8    1    2    3    4    5
 [9,]    9    1    2    3    4    5
[10,]   10    1    2    3    4    5
Kalin
la source
12

Pas simple, mais ça marche:

> t(sapply(a, unlist))
      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    1    1    2    3    4    5
 [2,]    2    1    2    3    4    5
 [3,]    3    1    2    3    4    5
 [4,]    4    1    2    3    4    5
 [5,]    5    1    2    3    4    5
 [6,]    6    1    2    3    4    5
 [7,]    7    1    2    3    4    5
 [8,]    8    1    2    3    4    5
 [9,]    9    1    2    3    4    5
[10,]   10    1    2    3    4    5
Paolo
la source
1
Avec des rjsonrésultats, colMeansne fonctionne que pour cette méthode! Je vous remercie!
mpyw
10

La matrixfonction intégrée a la possibilité de saisir des données byrow. Combinez cela avec un unlistsur votre liste de sources vous donnera une matrice. Nous devons également spécifier le nombre de lignes afin qu'il puisse fractionner les données non répertoriées. C'est:

> matrix(unlist(a), byrow=TRUE, nrow=length(a) )
      [,1] [,2] [,3] [,4] [,5] [,6]
 [1,]    1    1    2    3    4    5
 [2,]    2    1    2    3    4    5
 [3,]    3    1    2    3    4    5
 [4,]    4    1    2    3    4    5
 [5,]    5    1    2    3    4    5
 [6,]    6    1    2    3    4    5
 [7,]    7    1    2    3    4    5
 [8,]    8    1    2    3    4    5
 [9,]    9    1    2    3    4    5
[10,]   10    1    2    3    4    5
Kalin
la source
Ou remplir une matrice par des colonnes, puis transposer: t( matrix( unlist(a), ncol=length(a) ) ).
Kalin
8
t(sapply(a, '[', 1:max(sapply(a, length))))

où «a» est une liste. Cela fonctionnerait pour une taille de ligne inégale

Arihant
la source
3
> library(plyr)
> as.matrix(ldply(a))
      V1 V2 V3 V4 V5 V6
 [1,]  1  1  2  3  4  5
 [2,]  2  1  2  3  4  5
 [3,]  3  1  2  3  4  5
 [4,]  4  1  2  3  4  5
 [5,]  5  1  2  3  4  5
 [6,]  6  1  2  3  4  5
 [7,]  7  1  2  3  4  5
 [8,]  8  1  2  3  4  5
 [9,]  9  1  2  3  4  5
[10,] 10  1  2  3  4  5
apprendre
la source
1
Cela ne fonctionnera tout simplement pas si les lignes n'ont pas la même longueur, alors que do.call (rbind, ...) fonctionne toujours.
2013
des indices comment le faire fonctionner pour une taille de ligne inégale avec NA pour les données de ligne manquantes?
Arihant
1
@rwst En fait, do.call (rbind, ...) ne fonctionne pas pour les vecteurs de longueur inégale, sauf si vous avez vraiment l'intention de réutiliser le vecteur lors du remplissage de la ligne à la fin. Voir la réponse d'Arihant pour une manière qui remplit NAplutôt les valeurs à la fin.
Kalin