【问题标题】:Summing consecutive matrices in nested list r对嵌套列表 r 中的连续矩阵求和
【发布时间】:2016-03-28 03:15:08
【问题描述】:

我有一个 2x2 矩阵列表,看起来像这样:

matlist=
  list(structure(list(`1` = structure(c(8, 16, 3, 13), .Dim = c(2L, 2L)),
                    `2` = structure(c(6, 3, 0, 6), .Dim = c(2L, 2L)), 
                    `3` = structure(c(39,55, 15, 11), .Dim = c(2L, 2L)), 
                    `4` = structure(c(46, 53, 18,5), .Dim = c(2L, 2L)), 
                    `5` = structure(c(14, 6, 1, 12), .Dim = c(2L,2L)), 
                    `6` = structure(c(20, 6, 0, 12), .Dim = c(2L, 2L)), 
                    `7` = structure(c(4, 1, 0, 4), .Dim = c(2L, 2L))), 
                    .Names = c("1","2", "3", "4", "5", "6", "7" )), 
     structure(list(`1` = structure(c(38, 58, 0, 23), .Dim = c(2L, 2L)), 
                    `2` = structure(c(13, 10, 0, 7), .Dim = c(2L, 2L)), 
                    `3` = structure(c(22, 19, 1, 10), .Dim = c(2L,2L)), 
                    `4` = structure(c(8, 7, 0, 4), .Dim = c(2L, 2L)), 
                    `5` = structure(c(12,13, 3, 3), .Dim = c(2L, 2L)), 
                    `6` = structure(c(10, 8, 2, 2), .Dim = c(2L,2L)), 
                    `7` = structure(c(15, 14, 5, 5), .Dim = c(2L, 2L))), 
                    .Names = c("1", "2", "3", "4", "5", "6", "7"))
     )

看起来像这样:

lapply(matlist, head,4)

[[1]]
[[1]]$`1`
     [,1] [,2]
[1,]    8    3
[2,]   16   13

[[1]]$`2`
     [,1] [,2]
[1,]    6    0
[2,]    3    6

[[1]]$`3`
     [,1] [,2]
[1,]   39   15
[2,]   55   11

[[1]]$`4`
     [,1] [,2]
[1,]   46   18
[2,]   53    5


[[2]]
[[2]]$`1`
     [,1] [,2]
[1,]   38    0
[2,]   58   23

[[2]]$`2`
     [,1] [,2]
[1,]   13    0
[2,]   10    7

[[2]]$`3`
     [,1] [,2]
[1,]   22    1
[2,]   19   10

[[2]]$`4`
     [,1] [,2]
[1,]    8    0
[2,]    7    4

我想要做的是对每个元素内的每两个连续矩阵求和。因此,我想将第 1 和第 2 个矩阵、第 2 和第 3、第 3 和第 4 个矩阵相加......一直到“1”的最后两个矩阵。我想对 '2' 中的所有矩阵做同样的事情.... 对于较大列表中的所有嵌套列表,依此类推。

我可以使用 base 对列表中的所有矩阵求和:

lapply(matlist, function(x) Reduce('+', x))

或者我更喜欢使用purrr(因为这将适合一长串语法):

library(purrr)
matlist %>% map(~ Reduce('+', .))

[[1]]
     [,1] [,2]
[1,]  137   37
[2,]  140   63

[[2]]
     [,1] [,2]
[1,]  118   11
[2,]  129   54

如何在不使用循环的情况下对每个子列表中的每 2 个连续矩阵执行此操作 - 理想情况下我会有一个矢量化解决方案?

子列表 1 的前两个总和的期望输出示例:

 matlist[[1]][[1]]+matlist[[1]][[2]]
     [,1] [,2]
[1,]   14    3
[2,]   19   19

 matlist[[1]][[2]]+matlist[[1]][[3]]
     [,1] [,2]
[1,]   45   15
[2,]   58   17

【问题讨论】:

    标签: r


    【解决方案1】:

    这似乎有效:

    res = lapply(matlist, function(x) Map(`+`, head(x,-1), tail(x,-1)))
    
    # sample of the result:
    res[[1]][1:2]
    # $`1`
    #      [,1] [,2]
    # [1,]   14    3
    # [2,]   19   19
    # 
    # $`2`
    #      [,1] [,2]
    # [1,]   45   15
    # [2,]   58   17
    

    【讨论】:

    • 太棒了。非常优雅。
    【解决方案2】:

    虽然我喜欢@Frank 的解决方案的可读性,但我想添加另一种方法。如果将嵌套列表矩阵转换为数组列表,则可以对 Mapmapply 调用进行矢量化:

    set.seed(123)
    matlist <- replicate(100,
                         replicate(100, matrix(sample(4), nrow=2),
                                   simplify=FALSE),
                         simplify=FALSE)
    
    .array <- function(x) {
      a <- lapply(x, function(xx)array(unlist(xx), dim=c(2, 2, length(xx))))
      lapply(a, function(aa)aa[,,-dim(aa)[3]]+aa[,,-1])
    }
    
    frank <- function(x) {
      lapply(x, function(xx) Map(`+`, head(xx,-1), tail(xx,-1)))
    }
    
    library("rbenchmark")
    benchmark(frank(matlist), .array(matlist), order = "relative",
              columns = c("test", "replications", "elapsed", "relative"))
    #             test replications elapsed relative
    #2 .array(matlist)          100   0.460    1.000
    #1  frank(matlist)          100   2.386    5.187
    

    也许值得将您的数据结构更改为数组而不是矩阵的嵌套列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多