提问人:Papyrus 提问时间:7/18/2023 最后编辑:ThomasIsCodingPapyrus 更新时间:7/19/2023 访问量:64
是否有用于取消列表的 R 函数,其中可以控制递归级别?
Is there an R function for unlisting in which one can control the levels of recursion?
问:
我经常嵌套来自嵌套语句的对象列表,以便对象位于最后一级。当我想“扁平化”这些列表时,我使用 ;但是,有时我不能使用,因为它也会使最后一个对象的结构变平。lapply
unlist
unlist(recursive = T)
有没有办法控制列表中的级别,直到我可以应用取消列表递归?或者是否有任何其他 R 函数可以执行此操作?
例如,假设我有一个绘图列表,我希望将它们放在同一个列表级别,然后在面板中将所有绘图对齐在一起。
# Example list
library(ggplot2)
l0 <- list(
l1 = list(
l2 = list(
l3.1 = ggplot(data = data.frame()) + ggtitle("p1"),
l3.2 = ggplot(data = data.frame()) + ggtitle("p2")
)
)
)
# What I can do with unlist()
l0.u <- unlist(l0, recursive = F)
l0.u.r <- unlist(l0, recursive = T)
# The desired output
l0.desired <- unlist(unlist(l0, recursive = F),recursive = F)
答:
4赞
zx8754
7/18/2023
#1
创建一个递归函数,该函数在不递归的情况下保持取消列表,直到类为 ggplot:
f <- function(x){
if(all(sapply(x, function(i) inherits(i, c("gg", "ggplot"))))) {
x
} else f(unlist(x, recursive = FALSE))
}
x <- f(l0)
names(x)
# [1] "l1.l2.l3.1" "l1.l2.l3.2"
# plot 1st plot
x$l1.l2.l3.1
# plot 2nd plot
x$l1.l2.l3.2
评论
0赞
Konrad Rudolph
7/18/2023
不鼓励通过以下方式测试继承。您可以使用 : 更简单地进行测试。而且由于您使用,因此您不需要通话。class
inherits()
if (inherits(x, c("gg", "ggplot")))
if…else
return()
2赞
zx8754
7/18/2023
@KonradRudolph谢谢,编辑。无论如何,为了避免 sapply?(顺便说一句,随意编辑)
0赞
Konrad Rudolph
7/18/2023
嗯,看起来我完全误解了这个功能,因为我认为我们根本不需要这个功能。现在我很困惑为什么我们需要它......all(sapply(…))
0赞
zx8754
7/18/2023
@KonradRudolph我认为他们想进入剧情。但是由于 ggplot 是一个列表,我们不能只使用 unlist,所以一旦列表只包含 ggplots,我就停止了。
3赞
user2554330
7/19/2023
@Papyrus,可用于标识没有显式类集的对象。length(oldClass(x)) == 0
3赞
Joris C.
7/19/2023
#2
以下是使用 (in package) 的其他几种解决方案,它有一个专用选项来根据某些函数扁平化嵌套列表:rrapply()
rrapply
how = "flatten"
condition
## by class (not a pure list)
rrapply::rrapply(
l0,
condition = \(x) !inherits(x, "list"),
classes = c("list", "ANY"),
how = "flatten"
)
## by class (ggplot object)
rrapply::rrapply(
l0,
condition = ggplot2::is.ggplot,
classes = c("list", "ANY"),
how = "flatten"
)
## by name
rrapply::rrapply(
l0,
condition = \(x, .xname) grepl("l3", .xname),
classes = c("list", "ANY"),
how = "flatten"
)
## by level of nesting
rrapply::rrapply(
l0,
condition = \(x, .xpos) length(.xpos) == 3,
classes = c("list", "ANY"),
how = "flatten"
)
评论
lapply
for
lapply
unlist