【问题标题】:Get name of a functions inside a list获取列表中函数的名称
【发布时间】:2019-01-09 02:37:24
【问题描述】:

我希望达到的目标

所以我想在函数列表中获取函数的名称。

这是一个例子:

foo = list(foo1 = sum, foo2 = mean)

我希望从foo 中提取的是:

list("sum", "mean")

我希望它是一个函数,意思是:

> foo = list(foo1 = sum, foo2 = mean)
> super_function(foo)
list("sum", "mean")

我检查过的内容

申请名称:

> sapply(foo , names)
$`foo1`
NULL

$foo2
NULL

应用 deparse(substitute())

> my_f <- function(x)deparse(substitute(x))
> sapply(foo, my_f)
    foo1     foo2 
"X[[i]]" "X[[i]]" 

这两种想法都行不通....

更多背景:

这里有更多细节。不需要他们理解第一个问题,而是社区询问的额外细节。

我将这些函数用作用户给定的聚合函数。

data(iris)
agg_function<-function(data, fun_to_apply){
  res <- list()
  for (col_to_transform in names(fun_to_apply)){
    res[col_to_transform] <- (fun_to_apply[[col_to_transform]])(data[[col_to_transform]])
  }
  res
}


agg_function(iris, fun_to_apply = list("Sepal.Length" = mean, "Petal.Length" = sum))

结果是:

$`Sepal.Length`
[1] 5.843333

$Petal.Length
[1] 563.7

在本例中,我对两列 iris 执行聚合。但我希望在我的结果的每个字段的名称中包含执行函数的名称。 注意:这是对我正在做的事情的过度简化;

结论:

你有什么想法吗?

【问题讨论】:

  • 我是这么想的。那太容易了!
  • 不确定这是否可行。也许my_f1 &lt;- function(x) {lapply(x, deparse)} 可以提供帮助,尽管my_f1(foo) 的输出并不完全符合预期。
  • 好吧,让我们以foo = list(sd) 为例,函数代码中甚至没有提示这与“sd”有关。唯一限制候选者数量的是字节码(如何将字节码映射到函数名)和命名空间。但是考虑一下您在全局环境中拥有的功能。
  • 您能否提供更多关于您如何获取数据(乐趣列表)以及您想用它做什么的背景知识?也许有一种完全不同的方法。
  • 您需要以某种方式告诉/强制“用户”以字符串形式输入函数。然后你可以像这样使用它:get("sum")(1:3)

标签: r


【解决方案1】:

如果您只是从列表foo = list(foo1 = sum, foo2 = mean) 开始,那么这是不可能的。对list() 的调用将评估返回变量summean 指向的值的参数,但它不会记住这些变量名称。函数在 R 中没有名称。但函数可以分配给变量。然而,在 R 中,函数也可以没有名字。

您基本上刚刚创建了一个命名的函数列表。也可能是这样的

foo = list(foo1 = function(x) sum(x+1), 
    foo2 = function(x) mean(x+1))

这里我们也有函数,但是这些函数除了你在列表中给它们的名字之外没有“名字”。

您完成这项工作的唯一机会是在首先创建 foo 时使用 list() 以外的其他东西。或者让他们在函数调用中实际显式调用list()(这不是很实用)。

【讨论】:

    【解决方案2】:

    尽管您已经说过tidyverse 不适合您,但我会将此作为另一个想法添加。

    agg_function <- function(df, x, ...){
     df %>% 
        summarise_at(.vars = x, funs(...))
      }
    
    
    agg_function(iris, c("Sepal.Length", "Petal.Length"), mean, sum)  
      Sepal.Length_mean Petal.Length_mean Sepal.Length_sum Petal.Length_sum
    1          5.843333             3.758            876.5            563.7
    

    【讨论】:

    • 如果您已经将函数名称作为字符值c("mean", "sum"),我认为是否使用 tidyverse 并不重要。您也可以使用相同的输入轻松地执行此函数的非 tidyverse 版本。问题是输入数据不是函数的字符名称列表。
    【解决方案3】:

    您可以使用带有函数的列表作为字符串

    foo <- list(foo1 = "mean", foo2 = "sum")
    
    foo
    $foo1
    [1] "mean"
    
    $foo2
    [1] "sum"
    
    get(foo[[1]])(1:10)
    [1] 5.5
    get(foo[[2]])(1:10)
    [1] 55
    

    或使用rlang 包并执行类似的操作

    library(rlang)
    foo <- quos(foo1 = mean, foo2 = sum)
    
    getNames <- function(x) {
    +   sapply(x, function(x) x[[2]])
    + }
    
    getNames(foo)
    $foo1
    mean
    
    $foo2
    sum
    
    eval_tidy(foo[[1]])(1:10)
    [1] 5.5
    eval_tidy(foo[[2]])(1:10)
    [1] 55
    

    这也适用于非命名函数

    foo <- quos(foo1 = function(x) sum(x + 1), foo2 = sum)
    getNames(foo)
    $foo1
    function(x) sum(x + 1)
    
    $foo2
    sum
    
    eval_tidy(foo[[1]])(1:10)
    [1] 65
    

    【讨论】:

      猜你喜欢
      • 2010-10-09
      • 2021-02-12
      • 1970-01-01
      • 2021-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多