【问题标题】:Add multiple lists添加多个列表
【发布时间】:2015-12-07 12:59:50
【问题描述】:

我的研究结果存储在列表中。

我总共有 1000 个列表,所有这些列表都是相同的维度。

每个列表包含 39 个元素,它们是不同维度的矩阵。

我想将这些列表相加,然后除以 1000。

我想不出办法。

例子:

a<-matrix(0,nrow=5,ncol=6)
b<-matrix(0,nrow=2,ncol=10)

list1 <- list(a,b)

a<-matrix(0,nrow=5,ncol=6)
b<-matrix(0,nrow=2,ncol=10)

list2 <- list(a,b)

a<-matrix(0,nrow=5,ncol=6)
b<-matrix(0,nrow=2,ncol=10)

list3 <- list(a,b)

我要添加 list1 + list2 + list3...list1000

然后将最终列表中的每个元素除以 1000。

【问题讨论】:

  • 每个矩阵在每个列表中的位置都是相同的,所以我想将每个矩阵添加到同一个矩阵中
  • 包含真实结果的列表是否也将变量分开,例如list1list2、...?还是它们存储在其他列表中?
  • 它们存储在单独的 Rdata 文件中。

标签: r


【解决方案1】:

您可以结合使用MapReduce 并使用mget 将所有列表收集到一个列表中。

a<-matrix(1,nrow=5,ncol=6)
b<-matrix(10,nrow=2,ncol=10)

list1 <- list(a,b)
list2 <- list(a,b)
list3 <- list(a,b)

l <- mget(ls(pattern = '^list\\d+$'))
(fl <- Reduce(function(x, y) Map(`+`, x, y), l))

# [[1]]
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    3    3    3    3    3    3
# [2,]    3    3    3    3    3    3
# [3,]    3    3    3    3    3    3
# [4,]    3    3    3    3    3    3
# [5,]    3    3    3    3    3    3
# 
# [[2]]
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]   30   30   30   30   30   30   30   30   30    30
# [2,]   30   30   30   30   30   30   30   30   30    30

Map(`/`, fl, 1000)

# [[1]]
#       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
# [1,] 0.003 0.003 0.003 0.003 0.003 0.003
# [2,] 0.003 0.003 0.003 0.003 0.003 0.003
# [3,] 0.003 0.003 0.003 0.003 0.003 0.003
# [4,] 0.003 0.003 0.003 0.003 0.003 0.003
# [5,] 0.003 0.003 0.003 0.003 0.003 0.003
# 
# [[2]]
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03  0.03
# [2,] 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03  0.03

【讨论】:

  • 我正在努力摆脱 R 的 stringly typed code 所以我想提一下 R 有一个特定的语法来表示(否则无效)标识符,通过 `+`(即带反引号),并且在此处使用字符串虽然有效,但如果 R​​ 具有适当的类型系统,则 不应该 工作。也就是说,很好的答案。
  • 这是一个从 do.call、library 等继承下来的习惯。我会编辑
【解决方案2】:

我最近为此实现了一些递归实用程序函数。但是他们不检查前提条件(等长,元素的可和性)。

编辑:我已经修复了 cmets 中提到的问题。 for 循环被高阶函数所取代,该函数具有更好的错误行为。该函数还处理更复杂的列表结构,例如包含其他包含数字元素的列表的列表。它比 OP 要求的更多(也更复杂),但我认为值得保留,以防有人需要递归解决方案。

sum_numeric_lists <- function(...){
  lists <- list(...)

  if (length(unique(sapply(lists, length))) > 1) {
    stop("lists are not of equal length")
  }

  Map(function(...) {
    elems <- list(...)
    if (length(unique(sapply(elems, class))) > 1) {
      stop("corresponding elements have different types")
    }
    if (is.list(elems[[1]])) {
      sum_numeric_lists(...)
    } else if(is.numeric(elems[[1]])){
      Reduce(`+`, elems)
    } else {
      warning("lists contain types other than numeric, which are preserved as NULL elements")
      NULL
    }
  }, ...)

}


devide_numeric_list_by <- function(l, divisor){

  lapply(X = l, FUN = function(elem) {
    if (is.list(elem)) {
      devide_numeric_list_by(elem, divisor)
    } else if(is.numeric(elem)){
      elem / divisor
    } else {
      warning("lists contain types other than numeric, which are preserved as NULL elements")
      NULL
    }
  })

}

avg_numeric_lists <- function(...){
  sum_l <- sum_numeric_lists(...)
  devide_numeric_list_by(sum_l, length(list(...)))
}

一些测试:

avg_numeric_lists()
avg_numeric_lists(NULL)
avg_numeric_lists(list())
avg_numeric_lists(list(NULL))
avg_numeric_lists(list(1))
avg_numeric_lists(list(list(1)))

list1 <- list(m_first_lvl = matrix(sample(1:10, 20, replace = T), nrow=4, ncol=5),list(m_sec_lvl = matrix(sample(1:10, 6, replace = T), nrow=3, ncol=2)),"not_a_list_or_numeric",a_number = 1)
list2 <- list(m_first_lvl = matrix(sample(1:10, 20, replace = T), nrow=4, ncol=5),list(m_sec_lvl = matrix(sample(1:10, 6, replace = T), nrow=3, ncol=2)),"not_a_list_or_numeric",a_number = 2)
list3 <- list(m_first_lvl = matrix(sample(1:10, 20, replace = T), nrow=4, ncol=5),list(m_sec_lvl = matrix(sample(1:10, 6, replace = T), nrow=3, ncol=2)),"not_a_list_or_numeric",a_number = 3)
avg_numeric_lists(list1, list2, list3)

在全局环境中的所有列表上调用它(如 rawr 所建议的):

do.call(what = avg_numeric_lists, args = mget(ls(pattern = '^list\\d+$')))

【讨论】:

  • 你投反对票了吗?我在你指定之前写了这个答案,列表来自 1000 个 .RData 文件......但我想你会对另一个答案感到满意。
  • 我也没有对此投反对票,但它不是很好的代码。它很难阅读,循环可能应该被适当的高阶列表函数替换。此外,它可以从正确的错误处理中受益,而不是在结果中写入字符串(在极少数情况下这是合适的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-09
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
  • 2020-08-19
  • 1970-01-01
相关资源
最近更新 更多