2013-02-01 201 views
8

少用的rapply函数应该是很多问题的完美解决方案(如this one)。但是,它使用户编写的功能f无法知道它在树中的位置。在rapply中获取元素名称

有没有什么办法可以在rapply调用中将嵌套列表中元素的名称传递给f?不幸的是,rapply很快就拨打.Internal

回答

1

最近我用任意深度的嵌套列表挣扎着。最后,在我的案例中,我做出了或多或少可接受的决定。这不是对你的问题的直接回答(没有rapply的用法),但它似乎解决了同样的问题。我希望它可以有所帮助。

而不是尝试访问rapply里面的列表元素名称我生成的名称向量并查询它的元素。

# Sample list with depth of 3 
mylist <- list(a=-1, b=list(A=1,B=2), c=list(C=3,D=4, E=list(F=5,G=6))) 

在我的情况下生成名称向量是一个棘手的问题。具体而言,列表元素的名称应该是安全的,即没有.符号。

list.names <- strsplit(names(unlist(mylist)), split=".", fixed=TRUE) 
node.names <- sapply(list.names, function(x) paste(x, collapse="$")) 
node.names <- paste("mylist", node.names, sep="$") 
node.names 

[1] "mylist$a"  "mylist$b$A" "mylist$b$B" "mylist$c$C" "mylist$c$D" "mylist$c$E$F" 
[7] "mylist$c$E$G" 

下一步是按字符串名称访问列表元素。我发现没有比使用临时文件更好的了。

f <- function(x){ 
    fname <- tempfile() 
    cat(x, file=fname) 
    source(fname)$value 
} 

这里f刚刚返回的x,其中x是列表元素的全名的字符串值。

最后,我们可以在的查询列表中以伪递归方式的方式。

sapply(node.names, f) 
0

参考问题Find the indices of an element in a nested list?,你可以写:

rappply <- function(x, f) { 
    setNames(lapply(seq_along(x), function(i) { 
    if (!is.list(x[[i]])) f(x[[i]], .name = names(x)[i]) 
    else rappply(x[[i]], f) 
    }), names(x)) 
} 

然后,

> mylist <- list(a = 1, b = list(A = 1, B = 2), c = list(C = 1, D = 3)) 
> 
> rappply(mylist, function(x, ..., .name) { 
+ switch(.name, "a" = 1, "C" = 5, x) 
+ }) 
$a 
[1] 1 

$b 
$b$A 
[1] 1 

$b$B 
[1] 2 


$c 
$c$C 
[1] 5 

$c$D 
[1] 3