如何根据名称向量聚合列表中的矩阵?

时间:2016-01-19 21:07:39

标签: r list aggregate

我想根据存储在向量中的名称来聚合(求和)列表中的矩阵。这里有一些示例数据:

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)。

我首先尝试将agg.nam配置为

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

但是我在这一点上已经失败了,没有聚合。

2 个答案:

答案 0 :(得分:4)

您可以使用以下内容将相关列表元素捕获到矩阵中:

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

然后需要的是用colSums调用na.rm=TRUE(感谢@docendodiscimus指出这种简化):

colSums(do.call(rbind, lst[as.character(agg.nam)]), na.rm=TRUE)
# [1] 3 3 6 0 2 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)

1)abind 即使组成矩阵不是单行矩阵,这也有效。 abind从子列表L中创建一个三维数组,然后使用sum沿着并行元素应用na.rm = TRUE

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)数组这也有效,不使用任何软件包。除了使用Larray重新整形为3d数组之外,它的工作方式相同。 L来自上方。

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

3)mapply 使用mapply,这会定义一个删除NAs的并行总和,然后使用Reduce应用它。没有使用包裹。 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]]))