【问题标题】:Combine related nested list element vectors into matrices将相关的嵌套列表元素向量组合成矩阵
【发布时间】:2013-01-28 04:06:15
【问题描述】:

我有一个列表,其中每个列表元素本身都包含另一个包含多个名称对象的列表。这些命名对象中的每一个都是相同长度的向量。我的目标是通过连接向量有效地将相关对象(同名对象)组合成一个矩阵。

这是我正在使用的结构类型的示例。但是,在当前应用程序中,它来自 mclapply,因为它是一个并行化的多级模型,我认为没有办法返回列表列表。

> test=lapply(1:2,function(x){out = list(); out$t=rnorm(3)+x; out$p =rnorm(3)+ x+.1; return(out)})
> test
[[1]]
[[1]]$t
[1] 0.5950165 0.8827352 0.5614947

[[1]]$p
[1] 2.6144102 1.9688743 0.6241944


[[2]]
[[2]]$t
[1] 2.562030 1.832571 3.018756

[[2]]$p
[1] 1.7431969 0.5305784 2.6935106

这是实现我想要的粗略方法

> t.matrix = cbind(test[[1]]$t,test[[2]]$t)
> t.matrix
           [,1]     [,2]
[1,]  2.2094525 2.634907
[2,] -0.2822453 2.440666
[3,]  1.1704518 2.483424

但我希望能够为很长的列表(大约 100 万个元素)执行此操作,而我当前的解决方案无法扩展。

我想我可以使用 for 循环,但似乎必须有更好的方法来巧妙地使用 reduce 或 unlist 或 sapply 或类似的东西。

【问题讨论】:

  • 当您分享这类问题时使用set.seed() 总是很好,这样我们就可以将我们得到的输出与您打算得到的结果进行比较。
  • 感谢指点!我以后一定会这样做的。

标签: r list


【解决方案1】:
test <- lapply(1:4, function(x) { 
          out = list(); out$t=rnorm(3)+x; out$p =rnorm(3)+ x+.1; return(out)})

do.call(cbind, lapply(test, function(X) X[["t"]]))
## do.call(cbind, lapply(test, "[[", "t"))          ## Or, equivalently 
#           [,1]      [,2]     [,3]     [,4] 
# [1,] 0.7382887 0.9248296 4.205222 5.847823 
# [2,] 3.0321069 3.6806652 3.324739 3.695195 
# [3,] 2.3611483 1.9305901 1.574586 4.287534 

或者,同时处理两组列表元素:

elems <- c("t", "p")
sapply(elems, function(E) {
     do.call(cbind,
             lapply(test, function(X) {
                 X[[E]]
             }))
}, simplify=FALSE)
# $t
#           [,1]       [,2]     [,3]     [,4]
# [1,] 1.9226614 0.66463844 2.558517 2.743381
# [2,] 3.0026400 0.03238983 2.195404 3.824127
# [3,] 0.9371057 3.54638107 2.968717 2.434471
# 
# $p
#           [,1]     [,2]     [,3]     [,4]
# [1,] 0.8544413 2.942780 4.693698 4.158212
# [2,] 0.7172070 2.381438 4.869630 3.503361
# [3,] 3.1369674 2.464447 2.484968 3.626174

【讨论】:

    【解决方案2】:

    使用unlist(test, recursive = FALSE) 怎么样。但是,如果您希望将“p”和“t”分开,则需要不止一步完成。他们在一起:

    temp <- do.call(cbind, unlist(test, recursive = FALSE))
    temp
                 t         p        t        p
    [1,] 0.3735462 2.6952808 2.487429 1.794612
    [2,] 1.1836433 1.4295078 2.738325 3.611781
    [3,] 0.1643714 0.2795316 2.575781 2.489843
    

    将它们分开非常简单:

    temp[, colnames(temp) %in% "t"]
    #              t        t
    # [1,] 0.3735462 2.487429
    # [2,] 1.1836433 2.738325
    # [3,] 0.1643714 2.575781
    temp[, colnames(temp) %in% "p"]
    #              p        p
    # [1,] 2.6952808 1.794612
    # [2,] 1.4295078 3.611781
    # [3,] 0.2795316 2.489843
    

    这是我使用的数据:

    set.seed(1)
    test <- lapply(1:2, function(x) {
      out = list()
      out$t=rnorm(3)+x
      out$p =rnorm(3)+ x+.1
      return(out)
    })
    

    【讨论】:

    • 感谢您的回答,为您点赞。然而,我对 unlist 的一个犹豫是我看到的基准测试here 表明使用 unlist 并打开名称要慢得多。我想我可以使用您的解决方案并关闭 useNames 标志,但这会使重建有点棘手。
    • @DanielKessler,感谢您分享该链接。我不知道在使用 unlist 时保留名称会使函数慢得多!如果您知道您的数据组织良好,我想一种解决方法是选择最后的奇数列和偶数列,但这可能容易出错。我认为 Josh 的方法在这里绝对是最合适的。
    猜你喜欢
    • 1970-01-01
    • 2020-06-15
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多