重铸任何深度的嵌套列表
Recasting nested list of any depth
假设这个简化的例子:
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
然后我会用 reshape2::melt(L)
融化这个列表。这将输出以下内容:
value L3 L2 L4 L1
1 TRUE VAR Bar <NA> Foo
2 TRUE Dolor Ipsum VAR Lorem
在对值列中的某些单元格进行一些操作后,我希望将这个融化的列表重新转换为与 L
完全相同的嵌套列表结构——唯一的区别是我更新了一些value
个实例。
有什么想法可以实现吗?请记住,嵌套列表可以具有任意深度和不同深度。
一个选项是 relist
,在我们 unlist
ed L
之后
tmp <- unlist(L)
# make small changes
tmp[] <- FALSE
relist(tmp, L)
结果
$Foo
$Foo$Bar
$Foo$Bar$VAR
[1] FALSE
$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$VAR
[1] FALSE
L
长得像
$Foo
$Foo$Bar
$Foo$Bar$VAR
[1] TRUE
$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$VAR
[1] TRUE
另一种方法是在 rrapply
包中使用 rrapply()
,它具有选项 how = "melt"
和 how = "unmelt"
以在嵌套列表和熔化的 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
相对于relist()
的一个重要优点是不需要列表骨架对象(参见?relist
),因此我们在修改时不受骨架对象中定义的列表格式的约束融化了 data.frame,例如:
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
假设这个简化的例子:
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
然后我会用 reshape2::melt(L)
融化这个列表。这将输出以下内容:
value L3 L2 L4 L1
1 TRUE VAR Bar <NA> Foo
2 TRUE Dolor Ipsum VAR Lorem
在对值列中的某些单元格进行一些操作后,我希望将这个融化的列表重新转换为与 L
完全相同的嵌套列表结构——唯一的区别是我更新了一些value
个实例。
有什么想法可以实现吗?请记住,嵌套列表可以具有任意深度和不同深度。
一个选项是 relist
,在我们 unlist
ed L
tmp <- unlist(L)
# make small changes
tmp[] <- FALSE
relist(tmp, L)
结果
$Foo
$Foo$Bar
$Foo$Bar$VAR
[1] FALSE
$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$VAR
[1] FALSE
L
长得像
$Foo
$Foo$Bar
$Foo$Bar$VAR
[1] TRUE
$Lorem
$Lorem$Ipsum
$Lorem$Ipsum$Dolor
$Lorem$Ipsum$Dolor$VAR
[1] TRUE
另一种方法是在 rrapply
包中使用 rrapply()
,它具有选项 how = "melt"
和 how = "unmelt"
以在嵌套列表和熔化的 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
相对于relist()
的一个重要优点是不需要列表骨架对象(参见?relist
),因此我们在修改时不受骨架对象中定义的列表格式的约束融化了 data.frame,例如:
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