【问题标题】:get name of function assigned to variable in R获取分配给R中变量的函数名称
【发布时间】:2016-03-09 07:54:07
【问题描述】:

我有一个与this one 类似的问题,但有一个更特殊的情况。

考虑以下示例代码:

fun1 <- mean
fun2 <- max
fun3 <- median

现在我想获取分配给变量的函数名称为charachters。

虽然我理解this is not possible in general,但上述情况似乎有些特殊:

l <- list(fun1 = fun1, fun2 = fun2, fun3 = fun3)
l
$fun1
function (x, ...)
UseMethod("mean")
<bytecode: 0x2793818>
<environment: namespace:base>
$fun2
function (..., na.rm = FALSE)  .Primitive("max")
$fun3
function (x, na.rm = FALSE)
UseMethod("median")
<bytecode: 0x28382c8>
<environment: namespace:stats>

所以print(funX) 的输出包含分配给funX 的函数的名称。

如何将此信息提取到character 向量中?

【问题讨论】:

    标签: r higher-order-functions internals


    【解决方案1】:

    对 S3 泛型使用 findGeneric

    fun1 <- mean
    
    utils:::findGeneric("fun1", parent.frame())
    #[1] "mean"
    

    对于原始函数,您可以对函数体进行解析:

    fun2 <- max
    is.primitive(fun2)
    #[1] TRUE
    
    body <- deparse(fun2)
    m <- gregexpr('(?<=\\.Primitive\\(\\").*(?=\\")', body, perl = TRUE)
    regmatches(body, m)[[1]]
    #[1] "max"
    

    【讨论】:

    • 非常感谢您的好建议。你的第二个例子帮助我简化my solution。尽管如此,我还是无法将您的方法包装到一个函数中(如果is.primitivedeparse 否则使用findGeneric,因为funX 将被再次复制(在我的示例中为fun)当作为参数传递时到高阶函数。在这种情况下utils:::findGeneric(as.character(quote(fun)), parent.frame())返回"",也许这可以通过将parent.frame()替换为另一个envir来完成?
    • sapply(l,function(fun)utils:::findGeneric(as.character(quote(fun)),.GlobalEnv)) 返回 "" "" "",就像之前的 sapply(l,function(fun)utils:::findGeneric(as.character(quote(fun)),parent.frame()))...
    • @mschilli 查看sapply(l,function(fun) as.character(quote(fun)))。然后,你可以试试sapply(names(l), function(fun) utils:::findGeneric(fun, as.environment(l)))
    • 第二个 (as.environment(l)) 看起来非常很有希望。唯一的问题是(高阶)函数仍然需要知道(高阶)函数它们的环境之外的函数引用的名称。我需要的是类似于my answer 的东西,它获取(副本)函数引用并打印初始分配给它的函数的名称。 sapply 只是一个例子。 get_fun(fun1) 应返回 "mean"sapply(list(foo=fun2,fun3),get_fun) 应返回 "max" "median"(名称为 "foo" "")。
    • 对不起,这对我来说太复杂了。我真的不明白为什么这样的事情是必要的。为什么要将原语和泛型放在一个列表中?你不能把他们的名字放在一个列表中,然后在需要打电话给他们时使用getFunction吗?
    【解决方案2】:

    到目前为止我能想到的最好的方法是解析 print 输出:

    get_fun <- function(fun){
                 lines <- capture.output(print(fun))
                 pat <- "UseMethod|Primitive"
                 index <- grep(pat, lines)
                 line <- lines[index]
                 pat <- paste0(".*(", pat, ")")
                 chunk <- sub(pat, "", line)
                 words <- strsplit(chunk, "\"")[[1]]
                 return(words[2])
               }
    sapply(l, get_fun)
    
        fun1     fun2     fun3
      "mean"    "max" "median"
    

    但必须有更直接的方法。 毕竟不知何故,这些名字首先出现在print 输出中。


    编辑: 基于Rolandanswer,我能够将上述函数定义简化为:

    get_fun <- function(fun){
                 fun <- deparse(fun)
                 chunk <- tail(fun, 1)
                 words <- strsplit(chunk, "\"")[[1]]
                 return(words[2])
               }
    

    我仍然希望有一个更直接/更强大的解决方案(作为一个高阶函数,可能会返回 "fun" 用于无法确定/不存在真正底层函数的情况)。

    【讨论】:

      【解决方案3】:
      for (myfun in c(max,mean,median))
        print(gsub('^.*"(.*)".*','\\1',tail(deparse(myfun),1)))
      

      【讨论】:

      • AFAICT 这与my (updated) answer 的方法基本相同(基于Rolandanswer)。
      • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。谢谢!
      猜你喜欢
      • 2018-12-26
      • 2012-11-04
      • 1970-01-01
      • 2023-03-22
      • 2018-02-12
      • 1970-01-01
      • 2023-02-10
      • 2016-08-10
      • 2012-08-14
      相关资源
      最近更新 更多