【问题标题】:How to extract information from data nested in a multi-level list?如何从嵌套在多级列表中的数据中提取信息?
【发布时间】:2021-05-23 04:59:33
【问题描述】:

我正在尝试从嵌套在lapply 中的mapply 产生的复杂列表中提取数据。 目的是生成具有不同输入组合的模型模拟。 如果有帮助,请查看其他帖子:How to use mapply with sets of inputs of unequal lengths, using combinations of arguments?。

输出是一个如下所示的列表:

> output
[[1]]
              [,1]      [,2]      [,3]           
Variable1     Numeric,2 Numeric,5 Numeric,7
Variable2     Integer,2 Integer,5 Integer,7

[[2]]
              [,1]      [,2]      [,3]           
Variable1     Numeric,2 Numeric,5 Numeric,7
Variable2     Integer,2 Integer,5 Integer,7
...

此结构在列表中重复 n 次,与 lapply 请求的次数一样多。 我想从每个元素([[1]]、[[2]]、@987654332 @ 等)。

理想情况下,输出将是一个长格式的数据帧,列表级别和变量名称伴随着提取的值:

List_index    Column    Last_value_Variable1
[[1]]         [,1]      5
[[1]]         [,2]      2
[[1]]         [,3]      7
[[2]]         [,1]      8
[[2]]         [,2]      1
[[2]]         [,3]      9
...           ...     ...

如果需要,可以重命名列表索引和变量名。 我不确定我正在处理什么样的对象(一个列表,但是里面的嵌套列表......,而且有点不同......)。 我知道如何手动访问较低级别的最后一个元素(代码如下),但不知道如何迭代流程。

> output[[1]][,1]$Variable1[-1]
5
> output[[2]][,3]$Variable1[-1]
9

在output 上使用dput 会返回类似这样的内容(简化,因为实际的内容太长):

structure(list(
   c(1, 2), c(80L, 80L), c(2.2, 20.3),
   c(1, 2, 3, 4, 5), c(62L, 62L, 62L, 62L, 62L), c(1.7, 15.9, 24.4, 30.5, 35.2),
   c(1, 2, 3, 4, 5, 6, 7), c(25L, 25L, 25L, 25L, 25L, 25L, 25L), c(1.7, 15.9, 24.4, 30.5, 35.2, 39.1, 42.4)),
   #[rest of the list removed for clarity because it's too long]
   .Dim = c(16L, 11L),
   .Dimnames = list(c("Variable1", "Variable2", "Variable3", "Variable4", "Variable5", "Variable6", "Variable7", "Variable8", "Variable9", "Variable10", "Variable11", "Variable12", "Variable13", "Variable14", "Variable15", "Variable16"),
   NULL))

模型是一个函数,它返回一个数据框,其中包含 16 个变量和与模型输入之一相对应的可变数量的观察值。该模型使用一组 11 个参数输入进行了测试(因此在上面的 dput() 中使用了 .Dim = c(16L, 11L))。

我需要针对不同输入的组合运行模拟。 列表的第一级 ([[i]]) 对应于一个参数输入范围(馈入lapply 函数),第二级 ([,j]) 对应于馈入mapply 函数的另一组参数(在本例中为 11)。

【问题讨论】:

  • 你能提供一个dput()的数据示例吗?它使写答案变得容易得多。
  • 很遗憾,当我尝试创建您的对象时出现错误Error in attributes(.Data) <- c(attributes(.Data), attrib) : dims [product 176] do not match the length of object [9]
  • tidyr 包中的unnest_longer() 可能在这里会很有帮助。

标签: r list loops nested iteration


【解决方案1】:

@JCGruber 的建议帮助我找到了解决方案。 我在sapply 周围包裹了一个for 循环,以重复提取过程到列表的每个子元素(在我的例子中是11)。

l <- list()
for (i in 1:11)){
  l[i] <- as.data.frame(sapply(output, function(x) tail(x[,i]$Variable1, 1)), 4)
}
> l
[[1]]
[1]  0.8794 23.7201 46.5609

[[2]]
[1]  5.4517 25.7046 45.9574

[[3]]
[1]  8.6468 26.0620 43.4773

[[4]]
[1] 25.3687 40.9850 56.6014

[[5]]
[1] 28.9796 41.0070 53.0343

[[6]]
[1]  0.913 23.699 46.485

[[7]]
[1] 34.3093 45.8173 57.3253

[[8]]
[1] 30.9206 42.1212 53.3218

[[9]]
[1]  0.9130 22.4922 44.0714

[[10]]
[1] 44.4389 57.3425 70.2460

[[11]]
[1] 57.3268 67.5774 77.8280

我们可以从我感兴趣的变量 (variable1) 中找到列表的 11 个元素,以及每个子列表的最后 3 个值。抱歉,如果此示例中的确切值不对应。最终,每个列表元素的位置是最重要的。 现在处理数据要容易得多。 再次感谢 @JCGruber 让我走上正轨。

【讨论】:

    【解决方案2】:

    一般来说(因为没有提供数据),这应该很好用:

    sapply(output, function(x) x[,1]$Variable1[-1])
    

    列表可能很复杂(您的列表看起来很复杂),在我看来,您在提取一个值时所做的是正确的第一步。然后你只需要考虑如何编写一个函数来访问这个元素并将它放在另一个 *apply 循环中,让它在列表的每个元素上工作。

    顺便说一句,我现在可能会使用purrr::map_int(),因为它可以确保您从每次迭代中得到的是单个整数值。

    【讨论】:

    • 感谢@JBGruber 的回答和鼓励。我认为您通过sapply 让我走上了正轨。我是编程新手,但访问嵌套列表的元素如此复杂似乎很奇怪!如果有帮助,我已经使用dput() 添加了数据摘录...
    • 列表非常灵活,但有时也有点笨拙。值得注意的是,整个 tidyverse 都是基于这样的想法,即尽可能只使用 data.frames 以使事情变得更容易。
    猜你喜欢
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2021-11-05
    • 1970-01-01
    • 2020-08-05
    • 2017-12-20
    相关资源
    最近更新 更多