【问题标题】:pass function to ddply wrapped inside a function as part of that functions call作为该函数调用的一部分,将函数传递给包装在函数中的 ddply
【发布时间】:2014-01-31 00:05:17
【问题描述】:

我希望在函数中使用 ddply 根据用户确定的汇总统计数据(例如平均值、中位数、最小值、最大值)来汇总组,方法是将汇总函数的名称作为变量应用到函数中称呼。但是,我不确定如何将其传递给 ddply。

简单例如

library(plyr)
test.df<-data.frame(group=c("a","a","b","b"),value=c(1,5,5,15))
ddply(test.df,.(group),summarise, mean=mean(value, na.rm=TRUE))

我怎么能像下面这样设置它,将相关函数传递给 ddply (当然,在一个函数中,尽管一旦第一个问题解决了,这应该很简单)。请注意,每个汇总度量(平均值等)都需要 na.rm=TRUE。我可以通过为每个汇总统计量编写自己的替换函数来做到这一点,但这似乎过于复杂。

期望:

#fn<-"mean"     
#ddply(test.df,.(group),summarise, fn=fn(value, na.rm=TRUE))

感谢人们提供的任何帮助。

编辑! 感谢所有这些回复。我最初认为省略引号是有效的,但是这种方法,一旦 fn 作为函数调用的一部分,使用 getFunction 或 match.fun 也不起作用。我实际上希望开始工作的是下面的代码行(返回错误)。很抱歉没有在第一个实例中提供更详尽的示例......

test.df<-data.frame(group=c("a","a","b","b"),value=c(1,5,5,15))
my.fun <- function(df, fn="mean") {
    summary <- ddply(df,.(group),summarise, summary=match.fun(fn)(value, na.rm=T))
  return(summary)
}
my.fun(test.df, fn="mean")

【问题讨论】:

  • 我认为如果您从函数名称中删除引号,它将起作用fn&lt;-mean
  • 快速跟进。我最终通过避免使用 ddply 而使用聚合来规避这个问题。有了这个改变,正确的函数就会被调用,无论是在我的函数调用中引用还是不引用,以及使用或不使用 getFunction 或 match.fun。我仍然有兴趣知道如何使用 ddply 进行这项工作,但现在我认为它突出了能够利用基本函数以及一些出色的贡献包(如 plyr)的实用性。

标签: r plyr


【解决方案1】:

您在问题中提供的功能看起来应该可以工作。 (事实上​​,我花了一些时间才想起为什么它不会)。再次在这里,为了清楚起见,稍微改写了一下(我想在没有任何空格的情况下回答你的问题;)

df <- data.frame(
  group = c("a", "a" ,"b" ,"b" ), 
  value = c(1, 5, 5, 15)
)

my_fun <- function(df, fn = "mean") {
  fn <- match.fun(fn)
  ddply(df, .(group), summarise, summary = fn(value, na.rm = TRUE))
}

它不起作用的原因有点微妙,但归结为作用域(从变量名称中查找变量值的过程)的工作原理。 summarise() 使用非标准评估来查找数据框中的值以及调用它的环境。这适用于value,但不适用于fn,因为它不存在于调用summarise() 的位置,即在ddply() 中。

有两种解决方案:

  1. 使用添加到 plyr 的 here() 函数来解决 这个问题

    my_fun <- function(df, fn = "mean") {
      fn <- match.fun(fn)
      ddply(df, .(group), here(summarise), summary = fn(value, na.rm = TRUE))
    }
    my_fun(df, "mean")
    
  2. 稍微不那么简洁并使用显式函数:

    my_fun <- function(df, fn = "mean") {
      fn <- match.fun(fn)
      ddply(df, .(group), function(df) {
        summarise(df, summary = fn(value, na.rm = TRUE))
      })
    }
    my_fun(df, "mean")
    

我现在明白了如何在 plyr 的设计中首先避免这个问题,但它需要一些自定义 C/C++ 代码。它已在 dplyr 中修复,但不太可能移植回 plyr,因为它可能会破坏现有代码。

【讨论】:

  • 非常感谢 Hadley 的详细回复,并为缺少间距表示歉意。你的帖子澄清了我并没有发疯,但也促使我阅读了 dplyr,这听起来它还提供了速度方面的好处。更广泛地感谢 ggplot、lubridate 等。
【解决方案2】:

你可以使用getFunction:

fn<-"mean"     
ddply(test.df,.(group),summarise, fn=getFunction(fn)(value, na.rm=TRUE))
#  group fn
#1     a  3
#2     b 10

但是,如果您将其放入包装函数中,您可能会迷失在环境的丛林中。

【讨论】:

    【解决方案3】:

    它适用于match.fun:

    fn <- "mean"
    
    ddply(test.df, .(group), summarise, fn = match.fun(fn) (value, na.rm = TRUE))
    #  group fn
    # 1     a  3
    # 2     b 10
    

    【讨论】:

    • 感谢您的回复。我最初认为这会起作用,但是,一旦将要使用的函数指定为函数调用的一部分,这个响应或接下来的两个响应都不起作用。我用一个更具体的例子编辑了原始问题。
    • 查看原始问题下的 cmets 重新解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多