Jak utworzyć macierz z listy wektorów w języku R?


102

Cel: z listy wektorów o równej długości utwórz macierz, w której każdy wektor stanie się wierszem.

Przykład:

> 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

Chcę:

      [,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 

Odpowiedzi:


124

Jedną z opcji jest użycie 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
Więc różnica między this a standardową rbind () polega na tym, że do.call () przekazuje każdy element listy jako oddzielny argument - czy to prawda? do.call (rbind, a) jest równoważne rbind (a [[1]], a [[2]] ... a [[10]])?
Matt Parker,

5
Do.call () świetnie nadaje się do tego celu, chciałbym, żeby było lepiej "udokumentowane" w materiałach wprowadzających.
andrewj

16

simplify2arrayto podstawowa funkcja, która jest dość intuicyjna. Jednakże, ponieważ R domyślnie wypełnia dane kolumnami, będziesz musiał transponować dane wyjściowe. ( sapplyzastosowania simplify2array, jak udokumentowano w 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

Nie jest to proste, ale działa:

> 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
Z rjsonwynikami colMeansdziała tylko w przypadku tej metody! Dziękuję Ci!
mpyw

10

Wbudowana matrixfunkcja ma przyjemną opcję wprowadzania danych byrow. W połączeniu z unlistna liście źródeł otrzymasz macierz. Musimy również określić liczbę wierszy, aby można było rozbić dane niepubliczne. To jest:

> 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

Lub wypełnić matrycę kolumnami a następnie transpozycji: t( matrix( unlist(a), ncol=length(a) ) ).
Kalin

8
t(sapply(a, '[', 1:max(sapply(a, length))))

gdzie „a” to lista. Będzie działać dla nierównego rozmiaru wiersza


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
To po prostu nie zadziała, jeśli wiersze nie mają tej samej długości, podczas gdy do.call (rbind, ...) nadal działa.
pierwszy

jakieś wskazówki, jak sprawić, by działało to w przypadku nierównego rozmiaru wiersza z NA dla brakujących danych wiersza?
Arihant

1
@rwst Właściwie do.call (rbind, ...) nie działa dla wektorów o różnej długości, chyba że naprawdę zamierzasz użyć tego wektora ponownie podczas wypełniania wiersza na końcu. Zobacz odpowiedź Arihant, aby poznać sposób, w NAjaki zamiast tego wypełnia się wartościami na końcu.
Kalin,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.