R 使用ddply+;使用自定义函数进行变异?
我经常使用R 使用ddply+;使用自定义函数进行变异?,r,plyr,R,Plyr,我经常使用ddply,但历史上使用summary(偶尔使用mutate)和一些基本函数,如mean(),var1-var2,等等。我有一个数据集,我正试图在其中应用自定义,更复杂的函数,并开始尝试深入研究如何使用ddply实现这一点。我已经有了一个成功的解决方案,但我不明白为什么它是这样工作的,而不是为了更“正常”的功能 相关的 (我最终将我的解决方案建立在这个基础上) 下面是一个示例数据集: library(plyr) df <- data.frame(id = rep(lett
ddply
,但历史上使用summary
(偶尔使用mutate
)和一些基本函数,如mean()
,var1-var2
,等等。我有一个数据集,我正试图在其中应用自定义,更复杂的函数,并开始尝试深入研究如何使用ddply
实现这一点。我已经有了一个成功的解决方案,但我不明白为什么它是这样工作的,而不是为了更“正常”的功能
相关的
- (我最终将我的解决方案建立在这个基础上)
library(plyr)
df <- data.frame(id = rep(letters[1:3], each = 3),
value = 1:9)
我的设想是,ddply
根据id
的分组组合将df
拆分为“迷你”数据帧,然后我通过对df
中存在的列名调用mean()
添加一个新列。因此,我尝试实现一个函数扩展了这个想法:
# actually, my logical extension of the above was to use:
# ddply(..., mean = function(value) { mean(value) })
df_ply_2 <- ddply(df, .(id), mutate,
mean = function(df) { mean(df$value) })
Error: attempt to replicate an object of type 'closure'
排队时,看起来我必须这样做:
df_ply_4 <- df
df_ply_4$mean <- ddply(df, .(id), function(x) {
temp <- data.frame(mean = rep(mean(x$value), length(x$value)))
temp})$mean
再次感谢您的深入回答
根据@Gregor的最后评论更新 嗯,我使用了
rep(平均值(x),长度(x))
,因为对df_ply_3
的结果进行了观察(我承认在我第一次写这篇文章时没有仔细看它,我只是看到它没有给我一个错误!):
尝试将df\u ply\u 3
方法与df\u mean()
一起使用时出现错误:
“$中的错误您基本上是对的
ddply
确实可以根据grouper将数据分解为小型数据帧,并对每个数据块应用一个函数
使用ddply
,所有工作都是通过数据帧完成的,因此.fun
参数必须将一个(小型)数据帧作为输入,并返回一个数据帧作为输出
mutate
和summary
是适合此账单的函数(它们获取并返回数据帧)。您可以查看他们各自的帮助页面,或在ddply
之外的数据框上运行这些页面以查看此信息,例如
mutate(mtcars, mean.mpg = mean(mpg))
summarize(mtcars, mean.mpg = mean(mpg))
如果不使用mutate
或summary
,即仅使用自定义函数,则函数还需要将(迷你)数据帧作为参数,并返回数据帧
如果您使用mutate
或summary
,则传递给ddply
的任何其他函数都不会被ddply
使用,它们只是被传递给mutate
或summary
使用。mutate
和summary
使用的函数作用于数据列,而不是整个data.frame。这就是为什么
ddply(mtcars, "cyl", mutate, mean.mpg = mean(mpg))
请注意,我们不会传递mutate
函数。我们不会说ddply(mtcars,“cyl”,mutate,mean)
。我们必须告诉它该怎么做。在?mutate
中,..
的描述是“给出新列定义的命名参数”,与函数无关。(mean()真的与任何“自定义函数”不同吗?否)
因此,它不适用于匿名函数——或者根本不适用于函数。给它一个表情!您可以预先定义自定义函数
custom_function <- function(x) {mean(x + runif(length(x))}
ddply(mtcars, "cyl", mutate, jittered.mean.mpg = custom_function(mpg))
ddply(mtcars, "cyl", summarize, jittered.mean.mpg = custom_function(mpg))
tl;博士
为什么不能将mutate与自定义函数一起使用?是否只是“内置”函数返回ddply可以处理的某种类,而不是必须踢出完整的data.frame,然后只调用我关心的列
恰恰相反<代码>变异和汇总
将数据帧作为输入,将数据帧踢出作为返回。但是,mutate和summary是传递给ddply的函数,而不是mean或其他任何函数
Mutate和summary是方便的函数,您将在使用ddply
的99%时间内使用它们
如果不使用mutate/summary,那么函数需要获取并返回一个数据帧
如果您确实使用mutate/summary,那么您不会向它们传递函数,而是传递可以使用(迷你)数据框计算的表达式。如果它发生了变异,则返回值应该是附加到数据中的向量(根据需要循环)。如果是summary,则返回值应为单个值。您不需要传递函数,比如mean
;传递一个表达式,如mean(mpg)
dplyr怎么样? 这是在
dplyr
成为大事之前写的dplyr
消除了这个过程中的许多混乱,因为它基本上用mutate
或summary
替换了ddply
的嵌套,作为带有顺序函数的参数group\u by
后跟mutate
或summary
。我的答案的dplyr
版本是
library(dplyr)
group_by(mtcars, cyl) %>%
mutate(mean.mpg = mean(mpg))
新的列创建直接传递到
mutate
(或summary
),因此不存在关于哪个函数做什么的混淆。提问者的“自定义函数”的基本问题是,它试图处理来自全局环境的“太大”的对象对于多个较小的本地环境。似乎mutate
函数应该抛出一条信息更丰富的错误消息。我同意错误消息没有什么帮助,在很多情况下,将对象从全局环境(通常作为额外参数)传递给函数正是需要的,所以我看不出一个明显的解决方案。也许mutate
应该只产生错误消息:“不要向我发送函数。”这是一个很棒的答案,非常感谢您的帮助。我是函数新手,我认为另一个问题是假设定义一个“内联”函数将获取mini data.frame的名称(如mean=function(value){mean(value)}
将传递mini.df$value
,而它只是一个名为val的匿名对象
df <- data.frame(id = c(rep(letters[1:3], each = 3), "d"),
value = 1:10)
Error in `$<-.data.frame`(`*tmp*`, "mean", value = c(2, 5, 8, 10)) :
replacement has 4 rows, data has 10
mutate(mtcars, mean.mpg = mean(mpg))
summarize(mtcars, mean.mpg = mean(mpg))
ddply(mtcars, "cyl", mutate, mean.mpg = mean(mpg))
custom_function <- function(x) {mean(x + runif(length(x))}
ddply(mtcars, "cyl", mutate, jittered.mean.mpg = custom_function(mpg))
ddply(mtcars, "cyl", summarize, jittered.mean.mpg = custom_function(mpg))
mean.mpg.mutate = function(df) {
cbind.data.frame(df, mean.mpg = mean(df$mpg))
}
mean.mpg.summarize = function(df) {
data.frame(mean.mpg = mean(df$mpg))
}
ddply(mtcars, "cyl", mean.mpg.mutate)
ddply(mtcars, "cyl", mean.mpg.summarize)
library(dplyr)
group_by(mtcars, cyl) %>%
mutate(mean.mpg = mean(mpg))