给定一个嵌套列表,例如如下
lst <- list(
1,
list(list(c(4, 5, 4)), list(c(6, 7))),
list(c(2, 3, 3)),
list(list(c(5, 5, 6)), list(c(7, 7, 7)))
)
> str(lst)
List of 4
$ : num 1
$ :List of 2
..$ :List of 1
.. ..$ : num [1:3] 4 5 4
..$ :List of 1
.. ..$ : num [1:2] 6 7
$ :List of 1
..$ : num [1:3] 2 3 3
$ :List of 2
..$ :List of 1
.. ..$ : num [1:3] 5 5 6
..$ :List of 1
.. ..$ : num [1:3] 7 7 7
Run Code Online (Sandbox Code Playgroud)
比方说,最深切的级别为3,如向量的深处4 5 4,6 7,5 5 6和7 7 7在lst。
我想知道是否有一种方法可以只在那些最深层次上运行某个功能,而其他层次不受影响。例如,如果函数是unique,那么我的预期输出是
lstout <- list(
1,
list(list(c(4, 5)),list(c(6,7))),
list(c(2, 3, 3)),
list(list(c(5, 6)), list(7))
)
> str(lstout)
List of 4
$ : num 1
$ :List of 2
..$ :List of 1
.. ..$ : num [1:2] 4 5
..$ :List of 1
.. ..$ : num [1:2] 6 7
$ :List of 1
..$ : num [1:3] 2 3 3
$ :List of 2
..$ :List of 1
.. ..$ : num [1:2] 5 6
..$ :List of 1
.. ..$ : num 7
Run Code Online (Sandbox Code Playgroud)
似乎rapply不能只在最深层次上有选择地运行该功能。我不知道怎么做。
任何基本的 R想法或解决方案将不胜感激!
我们可以递归下降lst以找到最大深度,然后使用它再次递归下降,unique仅在最大深度处应用。不使用任何包。
maxDepth <- function(x, depth = 0) {
if (is.list(x)) max(sapply(x, maxDepth, depth+1))
else depth
}
lstUnique <- function(x, depth = maxDepth(x)) {
if (depth == 0) unique(x)
else if (is.list(x)) lapply(x, lstUnique, depth-1)
else x
}
lstUnique(lst)
Run Code Online (Sandbox Code Playgroud)
上面的一个变体是递归地向每个叶子添加一个等于其深度的类。然后我们可以使用rapply3次。首先使用rapply提取类并取最大值以找到最大深度。第二个用途rapply是仅应用于unique具有最大深度类的节点。第三,删除unique由于节点未达到最大深度而未被删除的任何剩余类。(第三个rapply,即下面的最后一行代码,如果可以为我们添加的类留下一些叶子就可以省略。)
addDepth <- function(x, depth = 0) {
if (is.list(x)) lapply(x, addDepth, depth+1)
else structure(x, class = format(depth))
}
lst2 <- addDepth(lst)
mx <- max(as.numeric(rapply(lst2, class))) # max depth
lst3 <- rapply(lst2, unique, classes = format(mx), how = "replace")
rapply(lst3, as.vector, how = "replace")
Run Code Online (Sandbox Code Playgroud)
请注意,如果您交替希望在所有叶子上运行 unique 而不仅仅是在最大深度叶子上运行,那么rapply在基础 R 中将起作用。
rapply(lst, unique, how = "replace")
Run Code Online (Sandbox Code Playgroud)
此替代方法确实需要使用包。首先,我们创建一个 data.tree dt,然后遍历它,将唯一的应用于满足 filterFun 的节点。
library(data.tree)
dt <- as.Node(lst)
dt$Do(function(x) x$"1" <- unique(x$"1"),
filterFun = function(x) x$level == dt$height)
print(dt, "1")
Run Code Online (Sandbox Code Playgroud)
rrapply 包提供了对 rapply 的增强,它也可以传递一个长度等于深度的位置向量,因此我们可以首先使用它来计算最大深度 mx,然后再次仅在该深度应用唯一。(更新rrapply了使用 how = "unlist" 的调用,而不是根据评论中的建议在之后应用 unlist。)
library(rrapply)
mx <- max(rrapply(lst, f = function(x, .xpos) length(.xpos), how = "unlist"))
uniq_mx <- function(x, .xpos) if (length(.xpos) == mx) unique(x) else x
rrapply(lst, is.numeric, uniq_mx)
Run Code Online (Sandbox Code Playgroud)