【问题标题】:Combine list of lists of matrices into a list of matrices将矩阵列表组合成矩阵列表
【发布时间】:2017-05-03 07:14:29
【问题描述】:

我有一个比较大的列表。列表的每个元素都是六个元素的列表。这些元素中的每一个都是具有固定行数和可变列数的矩阵。我想组合这些矩阵,这样我最终得到一个包含六个矩阵的列表,其中每个矩阵是对每个子列表中的相应元素调用 cbind 的结果,即第一个矩阵是内部所有第一个矩阵的 cbind列表,第二个矩阵是第二个矩阵的 cbind,等等。

例如:

 temp = list()
 temp[["a"]] = list(matrix(1, nrow=2, ncol=1), matrix(2, nrow=2,ncol=2))
 temp[["b"]] = list(matrix(3, nrow=2, ncol=3), matrix(4, nrow=2,ncol=4))

*调用一些 R 代码* 应该会输出

$`1`
     [,1] [,2] [,3] [,4]
[1,]    1    3    3    3
[2,]    1    3    3    3

$`3`
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    2    2    4    4    4    4
[2,]    2    2    4    4    4    4

我可以看到电话

mapply(cbind, temp[[1]], temp[[2]])

为这个玩具示例生成所需的输出,但我是否为一个大列表执行此操作,从执行到执行可能有可变数量的元素。

是否有一个优雅而高效的解决方案?

提前致谢!

【问题讨论】:

    标签: r list matrix apply


    【解决方案1】:
    do.call(mapply, c(cbind, temp))
    

    【讨论】:

    • 我喜欢这个,因为它只使用了内置函数,而且简洁。它按照玩具示例的设计工作,尽管大约 20 分钟后它还没有根据我的实际输入完成。这实际上比我生成数据所花费的时间要长,因此从性能的角度来看可能是不可接受的。不过,我对您的解决方案中实际发生的事情感到有些困惑。你介意解释一下它是如何工作的吗?谢谢。
    【解决方案2】:

    我们可以从purrrcbind 使用transpose

    library(purrr)
    lapply(transpose(temp), function(x) do.call(cbind, x))
    

    或者我们可以只使用transposemap 来自purrr

    transpose(temp) %>% 
                map(~matrix(unlist(.), nrow=2))
    #[[1]]
    #      [,1] [,2] [,3] [,4]
    #[1,]    1    3    3    3
    #[2,]    1    3    3    3
    
    #[[2]]
    #     [,1] [,2] [,3] [,4] [,5] [,6]
    #[1,]    2    2    4    4    4    4
    #[2,]    2    2    4    4    4    4
    

    我们也可以试试split 选项

    library(data.table)
    with(melt(temp), lapply(split(value, L1), matrix, nrow=2))
    

    基准测试

    set.seed(24)
    lst <- lapply(1:1e5, function(x) replicate(2, matrix(sample(1:5, 10, 
       replace=TRUE), nrow=2), simplify = FALSE))
    
    system.time({
    
     do.call(mapply, c(cbind, lst))
    
    })
    #  user  system elapsed 
    #   0.66    0.00    0.65 
    
    system.time({
      lst %>% pmap(cbind)
    
    })
    #  user  system elapsed 
    #   0.61    0.00    0.61 
    
    system.time({
      lapply(transpose(lst), function(x) do.call(cbind, x))
    })
    # user  system elapsed 
    #   0.39    0.00    0.40 
    
    library(microbenchmark)
    microbenchmark(Hong = do.call(mapply, c(cbind, lst)),
       ae = lst %>% pmap(cbind),
       akrun =  lapply(transpose(lst), function(x) do.call(cbind, x)), 
       unit = "relative")
    #    Unit: relative
    #   expr      min       lq     mean   median       uq      max neval
    #   Hong 1.716893 2.346379 1.975948 2.069316 2.012889 1.288478   100
    #     ae 1.623129 2.096566 1.697061 1.805834 1.702961 1.193930   100
    #  akrun 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   100
    

    【讨论】:

      【解决方案3】:

      purrr::pmap 并行迭代列表项并传递给您指定的函数,因此您只需使用即可获得所需的结果

      library(purrr)
      
      temp %>% pmap(cbind)
      ## [[1]]
      ##      [,1] [,2] [,3] [,4]
      ## [1,]    1    3    3    3
      ## [2,]    1    3    3    3
      ## 
      ## [[2]]
      ##      [,1] [,2] [,3] [,4] [,5] [,6]
      ## [1,]    2    2    4    4    4    4
      ## [2,]    2    2    4    4    4    4
      

      【讨论】:

      • 这在我看来是最好的解决方案。它既快速(我的输入不到 1 分钟)又简洁。
      猜你喜欢
      • 2013-04-13
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 2011-12-21
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多