2016-01-19 27 views
7

Tôi muốn tổng hợp (tổng) ma trận trong một danh sách theo tên được lưu trữ trong vectơ. Dưới đây một số ví dụ dữ liệu:Làm cách nào để tổng hợp ma trận trong danh sách dựa trên vectơ tên?

lst <- list("111"=matrix(c(1, 0, 6, NA, 1, 0), 
           nrow = 1, byrow = T), 
      "112"=matrix(c(6, 2, 2, 0, 3, NA), 
           nrow = 1, byrow = T), 
      "113"=matrix(c(2, 3, 0, 0, 1, 1), 
         nrow = 1, byrow = T)) 
agg.nam <- c(111,113) 

kết quả mong đợi của tôi là:

> res 
$ 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 3 3 6 0 2 1 

Vì vậy, các ma trận đầu tiên và thứ ba được tóm tắt (với na.rm = TRUE).

tôi đã cố gắng đầu tiên để tập hợp con các agg.nam:

lapply(lst, function(x) x[, which(names(x) %in% agg.nam)]) 

nhưng tôi đã thất bại trong thời điểm này, mà không tập hợp.

Trả lời

4

Bạn có thể lấy các yếu tố danh sách có liên quan vào một ma trận với:

do.call(rbind, lst[as.character(agg.nam)]) 
#  [,1] [,2] [,3] [,4] [,5] [,6] 
# [1,] 1 0 6 NA 1 0 
# [2,] 2 3 0 0 1 1 

Tất cả những gì sau đó được yêu cầu đang kêu gọi colSums với na.rm=TRUE (nhờ @docendodiscimus để chỉ ra đơn giản hóa này):

colSums(do.call(rbind, lst[as.character(agg.nam)]), na.rm=TRUE) 
# [1] 3 3 6 0 2 1 

Nếu ma trận có nhiều hàng, việc đơn giản hóa ở trên sẽ không thực sự hiệu quả và sau đây sẽ thực hiện thủ thuật tốt hơn:

# Grab relevant list elements 
mats <- lst[as.character(agg.nam)] 

# Replace any instance of NA with 0 
mats <- lapply(mats, function(x) { x[is.na(x)] <- 0 ; x }) 

# Sum them up 
Reduce("+", mats) 
#  [,1] [,2] [,3] [,4] [,5] [,6] 
# [1,] 3 3 6 0 2 1 
1

1) abind Điều này hoạt động ngay cả khi ma trận thành phần không phải là ma trận hàng đơn. abind tạo mảng 3 chiều ra khỏi danh sách con L và sau đó sum được áp dụng dọc theo các phần tử song song bằng cách sử dụng na.rm = TRUE.

library(abind) 

L <- lst[as.character(agg.nam)] 
apply(abind(L, along = 3), 1:2, sum, na.rm = TRUE) 

Trong trường hợp của dữ liệu đầu vào của câu hỏi chúng tôi nhận được ma trận đầu ra sau đây:

 [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 3 3 6 0 2 1 

2) mảng này cũng làm việc và không sử dụng bất kỳ gói. Nó hoạt động giống nhau ngoại trừ nó định hình lại L thành một mảng 3D sử dụng array. L là từ trên cao.

make3d <- function(List) array(unlist(List), c(dim(List[[1]]), length(List))) 
apply(make3d(L), 1:2, sum, na.rm = TRUE) 

3) mapply Sử dụng mapply này định nghĩa một khoản song song mà loại bỏ NA và sau đó áp dụng nó bằng cách sử Reduce. Không có gói nào được sử dụng. L là từ (1).

psum <- function(x, y) array(mapply(sum, x, y, MoreArgs = list(na.rm = TRUE)), dim(x)) 
Reduce(psum, L) 

3a) Một biến thể của (3) là:

sumNA <- function(...) sum(..., na.rm = TRUE) 
array(do.call(mapply, c(sumNA, L)), dim(L[[1]])) 
Các vấn đề liên quan