首页 > 解决方案 > R:展平列表列表的内部部分,同时保持其结构

问题描述

我正在进行一项模拟研究,我的结果存储在嵌套列表结构中。列表的第一级代表模型生成的不同超参数。第二个层次是同一模型的复制次数(改变种子)。

在下面的示例中,我列出了由两个超参数(hyperpar1 和 hyperpar2)控制的模型的输出,其中两个超参数都可以采用 2 个不同的值,从而导致生成的模型有 4 种不同的组合。此外,4 种可能的组合中的每一种都运行了两次(不同的种子),产生了 8 种可能的组合(如下所示str(res, max = 2))。最后,从模型的每个可能迭代(metric1 和 metric2)以及模型的两个参数的值中恢复了两个性能指标beta = list(b1 = value, b2 = value)

我的问题与最后一部分有关。我想展平列表beta并将列表中的每个组件作为包含它的上列表的组件,但保持开头描述的整个结构不变。

下面是一个例子:

数据样本。

res <-list(
  list(list(modeltype = "tree", time_iter = structure(0.7099, class = "difftime", units = "secs"),seed = 1, nobs = 75, hyperpar1 = 0.5, hyperpar2 = 0.5, metric1 = 0.4847, metric2 = 0.2576, beta = list(b1 = 0.575, b2 =0.745)),     
       list(modeltype = "tree", time_iter = structure(0.058 , class = "difftime", units = "secs"),seed = 2, nobs = 75, hyperpar1 = 0.5, hyperpar2 = 0.5, metric1 = 0.4013, metric2 = 0.2569, beta = list(b1 = 0.535, b2 =0.775))), 
  list(list(modeltype = "tree", time_iter = structure(0.046 , class = "difftime", units = "secs"),seed = 1, nobs = 75, hyperpar1 = 0.8, hyperpar2 = 0.5, metric1 = 0.4755, metric2 = 0.2988, beta = list(b1 = 0.541, b2 =0.702) ), 
       list(modeltype = "tree", time_iter = structure(0.0474, class = "difftime", units = "secs"),seed = 2, nobs = 75, hyperpar1 = 0.8, hyperpar2 = 0.5, metric1 = 0.2413, metric2 = 0.2147, beta = list(b1 = 0.545, b2 =0.793) )), 
  list(list(modeltype = "tree", time_iter = structure(0.0502, class = "difftime", units = "secs"),seed = 1, nobs = 75, hyperpar1 = 0.5, hyperpar2 = 1  , metric1 = 0.7131, metric2 = 0.5024, beta = list(b1 = 0.500, b2 =0.722) ), 
       list(modeltype = "tree", time_iter = structure(2.9419, class = "difftime", units = "secs"),seed = 2, nobs = 75, hyperpar1 = 0.5, hyperpar2 = 1  , metric1 = 0.4254, metric2 = 0.2824, beta = list(b1 = 0.555, b2 =0.712) )), 
  list(list(modeltype = "tree", time_iter = structure(0.041 , class = "difftime", units = "secs"),seed = 1, nobs = 75, hyperpar1 = 0.8, hyperpar2 = 1  , metric1 = 0.6709, metric2 = 0.4092, beta = list(b1 = 0.578, b2 =0.701) ), 
       list(modeltype = "tree", time_iter = structure(0.0396, class = "difftime", units = "secs"),seed = 2, nobs = 75, hyperpar1 = 0.8, hyperpar2 = 1  , metric1 = 0.4585, metric2 = 0.4115, beta = list(b1 = 0.501, b2 =0.777) )))

获得的输出的插图。

str(res[[1]][[1]], max = 3)
# List of 9
# $ modeltype: chr "tree"
# $ time_iter: 'difftime' num 0.7099
# ..- attr(*, "units")= chr "secs"
# $ seed     : num 1
# $ nobs     : num 75
# $ hyperpar1: num 0.5
# $ hyperpar2: num 0.5
# $ metric1  : num 0.485
# $ metric2  : num 0.258
# $ beta     :List of 2  #### <----- ( here is what I want to flatten/unlist ) 
# ..$ b1: num 0.575 
# ..$ b2: num 0.745

期望的输出(betas flattened)

str(res[[1]][[1]], max = 3)
# List of 9
# $ modeltype: chr "tree"
# $ time_iter: 'difftime' num 0.7099
# ..- attr(*, "units")= chr "secs"
# $ seed     : num 1
# $ nobs     : num 75
# $ hyperpar1: num 0.5
# $ hyperpar2: num 0.5
# $ metric1  : num 0.485
# $ metric2  : num 0.258
# $ b1: num 0.575 #### <----- ( here is new  because  ) 
# $ b2: num 0.745 #### <----- ( this part is flat now! )

PS:附带说明一下,模拟需要几天时间才能完成,而且并非所有模型中的参数数量都是恒定的;这就是为什么我想展平列表,beta不管它里面是什么。欢迎打包解决方案(例如,.data.tabledplyr)。谢谢。

标签: rlistvectordplyrdata.table

解决方案


我不确定这是否适用于真实数据,但它似乎产生了对上面示例数据的渴望。

map_depth(res, 2, flatten)

这是完整的输出str

library(purrr)

map_depth(res, 2, flatten) %>% str

#> List of 4
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.71
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.485
#>   .. ..$ metric2  : num 0.258
#>   .. ..$ b1       : num 0.575
#>   .. ..$ b2       : num 0.745
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.058
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.401
#>   .. ..$ metric2  : num 0.257
#>   .. ..$ b1       : num 0.535
#>   .. ..$ b2       : num 0.775
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.046
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.475
#>   .. ..$ metric2  : num 0.299
#>   .. ..$ b1       : num 0.541
#>   .. ..$ b2       : num 0.702
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.0474
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.241
#>   .. ..$ metric2  : num 0.215
#>   .. ..$ b1       : num 0.545
#>   .. ..$ b2       : num 0.793
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.0502
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.713
#>   .. ..$ metric2  : num 0.502
#>   .. ..$ b1       : num 0.5
#>   .. ..$ b2       : num 0.722
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 2.94
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.425
#>   .. ..$ metric2  : num 0.282
#>   .. ..$ b1       : num 0.555
#>   .. ..$ b2       : num 0.712
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.041
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.671
#>   .. ..$ metric2  : num 0.409
#>   .. ..$ b1       : num 0.578
#>   .. ..$ b2       : num 0.701
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: num 0.0396
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.459
#>   .. ..$ metric2  : num 0.411
#>   .. ..$ b1       : num 0.501
#>   .. ..$ b2       : num 0.777

reprex 包于 2021-02-21 创建(v0.3.0)

更新
上述方法的问题是所有其他变量都转换为numeric,这是不可取的,因为time_iter它最初是一个difftime对象。

下面的方法更详细,但不会将其他变量转换为numeric

res %>%
  map(
    ~ modify(.x, function(x) {
      x <- append(x, unlist(x$beta))
      x$beta <- NULL 
      x
      })

下面是输出str

res %>%
  map(
    ~ modify(.x, function(x) {
      x <- append(x, unlist(x$beta))
      x$beta <- NULL 
      x
      })
  ) %>% str

#> List of 4
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.7099
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.485
#>   .. ..$ metric2  : num 0.258
#>   .. ..$ b1       : num 0.575
#>   .. ..$ b2       : num 0.745
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.058
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.401
#>   .. ..$ metric2  : num 0.257
#>   .. ..$ b1       : num 0.535
#>   .. ..$ b2       : num 0.775
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.046
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.475
#>   .. ..$ metric2  : num 0.299
#>   .. ..$ b1       : num 0.541
#>   .. ..$ b2       : num 0.702
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.0474
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 0.5
#>   .. ..$ metric1  : num 0.241
#>   .. ..$ metric2  : num 0.215
#>   .. ..$ b1       : num 0.545
#>   .. ..$ b2       : num 0.793
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.0502
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.713
#>   .. ..$ metric2  : num 0.502
#>   .. ..$ b1       : num 0.5
#>   .. ..$ b2       : num 0.722
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 2.9419
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.5
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.425
#>   .. ..$ metric2  : num 0.282
#>   .. ..$ b1       : num 0.555
#>   .. ..$ b2       : num 0.712
#>  $ :List of 2
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.041
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 1
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.671
#>   .. ..$ metric2  : num 0.409
#>   .. ..$ b1       : num 0.578
#>   .. ..$ b2       : num 0.701
#>   ..$ :List of 10
#>   .. ..$ modeltype: chr "tree"
#>   .. ..$ time_iter: 'difftime' num 0.0396
#>   .. .. ..- attr(*, "units")= chr "secs"
#>   .. ..$ seed     : num 2
#>   .. ..$ nobs     : num 75
#>   .. ..$ hyperpar1: num 0.8
#>   .. ..$ hyperpar2: num 1
#>   .. ..$ metric1  : num 0.459
#>   .. ..$ metric2  : num 0.411
#>   .. ..$ b1       : num 0.501
#>   .. ..$ b2       : num 0.777

reprex 包于 2021-03-27 创建(v0.3.0)


推荐阅读