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 

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

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

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

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

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


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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.