将函数传递给ddply包装在函数内部作为函数调用的一部分

时间:2014-01-12 03:39:45

标签: r plyr

我希望在函数中使用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))

感谢您提供的任何帮助。

EDIT! 谢谢大家对这些回复。我最初认为遗漏引号是有效的,但是这种方法,也没有使用getFunction或match.fun工作一旦fn特定作为函数调用的一部分。我实际上希望工作的是下面的代码(返回错误)。抱歉没有提供更全面的例子......

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")

3 个答案:

答案 0 :(得分:4)

您在问题中提供的功能看起来应该有效。 (事实上​​我花了一些时间来记住它为什么不会这样做)。在这里再次,为了清晰起见略有改写(Iwastemptedtoansweryourquestionwithoutanyspacesiniteither;)

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")
    
  3. 我现在明白了如何在plyr的设计中首先避免这个问题,但它需要一些自定义的C / C ++代码。它已在dplyr中修复,但不太可能被移植回到plyr,因为它可能会破坏现有代码。

答案 1 :(得分:2)

您可以使用getFunction

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

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

答案 2 :(得分:1)

适用于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