问题
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 unlist
ed 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