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