2016-01-19 5 views
7

ベクトルに格納されている名前に従ってリスト内の行列を集計(合計)したい。ここではいくつかのサンプルデータ:名前のベクトルに基づいてリスト内の行列を集計する方法は?

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) 

私の期待される結果である:

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

そこで、第一及び第三のマトリックスは(na.rm = TRUEで)合計されます。

Iはagg.namをサブセットするために第1の試み:

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

私は既に凝集することなく、この点で失敗しました。

答えて

4

あなたはとのマトリックスに関連するリストの要素をつかむことができます。

colSums(do.call(rbind, lst[as.character(agg.nam)]), na.rm=TRUE) 
# [1] 3 3 6 0 2 1 
:それはその後、(この単純化を指摘するために@docendodiscimusのおかげで) na.rm=TRUEcolSumsを呼び出している必要とするすべての

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 

行列に複数の行が含まれていた場合、上記の単純化は実際には機能しません。次のようにすれば、トリックはより良くなります。

# 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これは、構成行列が単列行列でない場合でも機能します。 abindは、サブリストLから3次元配列を作成し、次にna.rm = TRUEを使用して平行要素に沿ってsumが適用されます。私たちは、次の出力行列を取得し、質問の入力データの場合

library(abind) 

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

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

2)配列これも動作し、任意のパッケージを使用しません。 arrayを使用してLを3次元配列に再形成することを除いて、同じ動作をします。 Lは上からのものである。

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

3)mapplyこれは、NASを除去した後、Reduceを使用してそれを適用する並列和を定義mapplyを使用します。パッケージは使用されません。 Lは(1)からのものである。

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

3A)(3)のばらつきがある:

sumNA <- function(...) sum(..., na.rm = TRUE) 
array(do.call(mapply, c(sumNA, L)), dim(L[[1]]))