Как мне сделать матрицу из списка векторов в R?


102

Цель: из списка векторов одинаковой длины создать матрицу, в которой каждый вектор станет строкой.

Пример:

> 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

Я хочу:

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

Ответы:


124

Один из вариантов - использовать 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
Итак, разница между этим и стандартным rbind () заключается в том, что do.call () передает каждый элемент списка как отдельный аргумент - это правильно? do.call (rbind, a) эквивалентен rbind (a [[1]], a [[2]] ... a [[10]])?
Мэтт Паркер,

5
do.call () отлично подходит для этой цели, я бы хотел, чтобы она была лучше "задокументирована" во вводных материалах.
andrewj

16

simplify2arrayэто базовая функция, которая довольно интуитивно понятна. Однако, поскольку R по умолчанию сначала заполняет данные по столбцам, вам нужно будет транспонировать вывод. ( sapplyиспользует simplify2array, как описано в 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

Непросто, но работает:

> 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
С rjsonрезультатами, colMeansработает только для этого метода! Спасибо!
mpyw

10

Встроенная matrixфункция имеет удобную возможность ввода данных byrow. Объедините это с в unlistвашем списке источников, и вы получите матрицу. Нам также необходимо указать количество строк, чтобы можно было разбить данные, не указанные в списке. То есть:

> 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

Или заполнить матрицу по столбцам , а затем транспонировать: t( matrix( unlist(a), ncol=length(a) ) ).
Калин

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

где «а» - это список. Будет работать с неравным размером строки


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
Это просто не сработает, если строки не имеют одинаковой длины, а do.call (rbind, ...) все еще работает.
rwst

какие-либо подсказки, как заставить его работать для неравного размера строки с NA для отсутствующих данных строки?
Arihant

1
@rwst На самом деле do.call (rbind, ...) не работает для векторов неравной длины, если только вы действительно не собираетесь повторно использовать вектор при заполнении строки в конце. См. Ответ Ариханта, чтобы узнать, NAкак вместо этого подставляются значения в конце.
Калин
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.