我希望在函数中使用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))
感谢人们提供的任何帮助。
编辑!感谢大家的回复。我最初认为去掉引号是可行的,但这种方法,也不使用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")
您在问题中提供的函数看起来应该可以工作。(事实上,我花了一些时间才想起为什么它不会)。它又来了,为了清晰起见,稍微重写了一下(我很乐意在没有任何空格的情况下回答你的问题;)
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()
中。
有两种解决方案:
使用添加到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")
稍微不那么简洁,使用显式函数:
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")
我现在明白了在plyer的设计中如何首先避免这个问题,但它需要一些自定义的C/C++代码。它在dplyr中已修复,但不太可能移植回plyr,因为它可能会破坏现有代码。
您可以使用getFunction
:
fn<-"mean"
ddply(test.df,.(group),summarise, fn=getFunction(fn)(value, na.rm=TRUE))
# group fn
#1 a 3
#2 b 10
然而,如果您将其放入包装器函数中,您可能会迷失在环境的丛林中。
它与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