如何从列表中获取变量名称

时间:2016-04-01 22:03:19

标签: r list evaluation

我有一系列功能,其中还包含一个用户定义的功能:

> fun <- function(x) {x}
> funs <- c(median, mean, fun)

是否可以从此列表中获取函数名称作为字符串?到目前为止,我唯一的解决方法是创建包含函数名称为vector的vector:

> fun.names <- c("median", "mean", "fun")

当我想获取变量名称时,我会使用这个技巧(如果这不正确请更正确),但是你可以看到它只适用于一个变量而不是列表:

> as.character(substitute(mean))
[1] "mean"

> as.character(substitute(funs))
[1] "funs"

是否还有适用于列表的内容?如果列表包含函数或数据类型,有什么区别吗?

修改 我需要将这个函数列表(加上另一个数据)传递给另一个函数。然后列表中的那些函数将应用于数据集。需要函数名,因为如果列表中有多个函数传递,我希望能够确定应用了哪个函数。到目前为止,我一直在使用它:

window.size   <- c(1,2,3)
combinations  <- expand.grid(window.size, c(median, mean))
combinations  <- cbind(combinations, rep(c("median","mean"), each = length(window.size)))

2 个答案:

答案 0 :(得分:2)

一般来说,这是不可能的。考虑funs

的这个定义
funs <- c(median,mean,function(x) x);

在这种情况下,根本没有与用户定义的功能相关联的名称。 R中没有规则表明所有函数必须在任何时间点绑定到名称。

如果你想开始对 所有这些lambdas的定义做出一些假设,那么可能会开启。

一个想法是在每个函数的闭包环境中搜索与函数本身匹配(相同)的条目,然后使用该名称。由于比较工作,这将导致性能损失,但如果您不必重复运行它,则可以容忍:

getFunNameFromClosure <- function(fun) names(which(do.call(c,eapply(environment(fun),identical,fun)))[1L]);

演示:

fun <- function(x) x;
funs <- c(median,mean,fun);
sapply(funs,getFunNameFromClosure);
## [1] "median" "mean"   "fun"

<强>注意事项:

1:如前所述,这不适用于从未绑定到名称的函数。此外,它不适用于其闭包环境不包含对函数的绑定的函数。如果函数绑定到与其闭包不同的环境中的名称(通过返回值,超级赋值或assign()调用)或者其闭包环境已明确更改,则可能会发生这种情况。

2:可以将函数绑定到多个名称。因此,eapply()搜索得到的名称可能不是您期望的名称。这是一个很好的证明:

getFunNameFromClosure(ls); ## gets wrong name
## [1] "objects"
identical(ls,objects); ## this is why
## [1] TRUE

答案 1 :(得分:1)

这是一种hacky方法:

funs <- list(median, mean)

fun_names = sapply(funs, function(x) {
  s = as.character(deparse(eval(x)))[[2]]
  gsub('UseMethod\\(|[[:punct:]]', '', s)
})

names(funs) <- fun_names

funs

$median
function (x, na.rm = FALSE) 
UseMethod("median")
<bytecode: 0x103252878>
<environment: namespace:stats>

$mean
function (x, ...) 
UseMethod("mean")
<bytecode: 0x103ea11b8>
<environment: namespace:base>

combinations  <- expand.grid(window.size, fun_names, c(median, mean))