Як зробити матрицю зі списку векторів у 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))))

де 'a' - це список. Буде працювати для неоднакового розміру рядків


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 для даних про рядки, що відсутні?
Аріхант

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