Recasting nested list of any depth

杀马特。学长 韩版系。学妹 提交于 2021-02-19 06:06:54

问题


Assume this simplified example:

L <- list()

L$Foo <- list()
L$Foo$Bar <- list()
L$Foo$Bar$VAR <- TRUE

L$Lorem <- list()
L$Lorem$Ipsum <- list()
L$Lorem$Ipsum$Dolor <- list()
L$Lorem$Ipsum$Dolor$VAR <- TRUE

I will then melt this list with reshape2::melt(L). That will output the following:

  value    L3    L2   L4    L1
1  TRUE   VAR   Bar <NA>   Foo
2  TRUE Dolor Ipsum  VAR Lorem

After some operations on certain cells in the value column, I'm then looking to recast this melted list into the exact same nested list structure as L—the only difference being that I updated a few of the value instances.

Any ideas how to achieve this? Please keep in mind that the nested lists can have any, and varying, depth.


回答1:


An option is relist, after we unlisted L

tmp <- unlist(L)
# make small changes
tmp[] <- FALSE
relist(tmp, L)

Result

$Foo
$Foo$Bar
$Foo$Bar$VAR
[1] FALSE



$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$VAR
[1] FALSE

L looks like

$Foo
$Foo$Bar
$Foo$Bar$VAR
[1] TRUE



$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$VAR
[1] TRUE



回答2:


An alternative could be to use rrapply() in the rrapply-package which has options how = "melt" and how = "unmelt" to transform between nested lists and melted data.frames:

library(rrapply)

L <- list(Foo = list(Bar = list(VAR = TRUE)), Lorem = list(Ipsum = list(Dolor = list(VAR = TRUE))))

## melt to data.frame
(L1 <- rrapply(L, how = "melt"))
#>      L1    L2    L3   L4 value
#> 1   Foo   Bar   VAR <NA>  TRUE
#> 2 Lorem Ipsum Dolor  VAR  TRUE

## cast back to nested list
L2 <- rrapply(L1, how = "unmelt")

str(L2)
#> List of 2
#>  $ Foo  :List of 1
#>   ..$ Bar:List of 1
#>   .. ..$ VAR: logi TRUE
#>  $ Lorem:List of 1
#>   ..$ Ipsum:List of 1
#>   .. ..$ Dolor:List of 1
#>   .. .. ..$ VAR: logi TRUE

identical(L2, L)
#> [1] TRUE

An important advantage with respect to relist() is that no list skeleton object is needed (see ?relist), so we are not constrained by the list format defined in the skeleton object when modifying the melted data.frame, e.g.:

L_unlist <- unlist(as.relistable(L))

## this change has no effect when relisting
## as the original list is used as skeleton
names(L_unlist)[1] <- "Foo.Bar.Test"

relist(L_unlist)
#> $Foo
#> $Foo$Bar
#> $Foo$Bar$VAR
#> [1] TRUE
#> 
#> $Lorem
#> $Lorem$Ipsum
#> $Lorem$Ipsum$Dolor
#> $Lorem$Ipsum$Dolor$VAR
#> [1] TRUE
#> 
#> attr(,"class")
#> [1] "relistable" "list"

## here it does behave as expected
L_melt <- rrapply(L, how = "melt")
L_melt[1, "L3"] <- "Test"

rrapply(L_melt, how = "unmelt")
#> $Foo
#> $Foo$Bar
#> $Foo$Bar$Test
#> [1] TRUE
#> 
#> $Lorem
#> $Lorem$Ipsum
#> $Lorem$Ipsum$Dolor
#> $Lorem$Ipsum$Dolor$VAR
#> [1] TRUE


来源:https://stackoverflow.com/questions/66250453/recasting-nested-list-of-any-depth

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!