Làm cách nào để tạo ma trận từ danh sách các vectơ trong R?


102

Mục tiêu: từ danh sách các vectơ có độ dài bằng nhau, tạo một ma trận trong đó mỗi vectơ trở thành một hàng.

Thí dụ:

> 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

Tôi muốn:

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

Câu trả lời:


124

Một tùy chọn là sử dụng 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
Vì vậy, sự khác biệt giữa điều này và rbind () tiêu chuẩn là do.call () chuyển từng mục danh sách như một đối số riêng biệt - có đúng không? do.call (rbind, a) tương đương với rbind (a [[1]], a [[2]] ... a [[10]])?
Matt Parker

5
do.call () là rất tốt cho mục đích này, tôi ước gì nó được "ghi lại" tốt hơn trong các tài liệu giới thiệu.
andrewj

16

simplify2arraylà một hàm cơ sở khá trực quan. Tuy nhiên, vì mặc định của R là điền dữ liệu theo cột trước tiên, bạn sẽ cần chuyển đầu ra. ( sapplysử dụng simplify2array, như được ghi trong tài liệu 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

Không đơn giản, nhưng nó hoạt động:

> 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
Với rjsonkết quả, colMeanschỉ hoạt động cho phương pháp này! Cảm ơn bạn!
mpyw

10

Việc xây dựng trong matrixchức năng có quyền lựa chọn tốt đẹp để nhập dữ liệu byrow. Kết hợp nó với một unlisttrong danh sách nguồn của bạn sẽ cho bạn một ma trận. Chúng ta cũng cần chỉ định số hàng để nó có thể chia nhỏ dữ liệu không công khai. Đó là:

> 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

Hoặc điền vào một ma trận của các cột và sau đó transpose: t( matrix( unlist(a), ncol=length(a) ) ).
Kalin

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

trong đó 'a' là một danh sách. Sẽ hoạt động cho kích thước hàng không bằng nhau


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
Điều này chỉ đơn giản là sẽ không hoạt động nếu các hàng không có cùng độ dài, trong khi do.call (rbind, ...) vẫn hoạt động.
rwst

bất kỳ manh mối làm thế nào để làm cho nó hoạt động cho kích thước hàng không bằng nhau với NA cho dữ liệu hàng bị thiếu?
Arihant

1
@rwst Trên thực tế, do.call (rbind, ...) không hoạt động đối với các vectơ có độ dài không bằng nhau, trừ khi bạn thực sự có ý định sử dụng lại vectơ khi điền vào hàng ở cuối. NAThay vào đó, hãy xem phản hồi của Arihant để biết cách điền các giá trị vào cuối.
Kalin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.