I use ddply
相当频繁,但历史上有summarize
(偶尔mutate
)并且只有基本功能,例如mean()
, var1 - var2
等等。我有一个数据集,我试图在其中应用一个自定义的、更复杂的函数,并开始尝试深入研究如何做到这一点ddply
。我有一个成功的解决方案,但我不明白why它的工作原理与更多“正常”功能相比是这样的。
Related
- ddply {plyr} 无法识别自定义函数... https://stackoverflow.com/questions/11556877/custom-function-not-recognized-by-ddply-plyr-it-tells-me-that-my-function-is
- 如何将变量传递给 ddply 中的自定义函数? https://stackoverflow.com/questions/20845409/how-do-i-pass-variables-to-a-custom-function-in-ddply
-
r-help: [R] 正确使用 ddply 及其自身功能 http://grokbase.com/t/r/r-help/1255y8qvty/r-correct-use-of-ddply-with-own-function(我最终的解决方案基于此)
这是一个示例数据集:
library(plyr)
df <- data.frame(id = rep(letters[1:3], each = 3),
value = 1:9)
通常情况下,我会使用ddply
像这样:
df_ply_1 <- ddply(df, .(id), mutate, mean = mean(value))
我对此的想象是ddply
splits df
基于分组组合的“迷你”数据框id
,然后我通过调用添加一个新列mean()
在存在于的列名上df
。因此,我尝试实现一个函数扩展了这个想法:
# 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'
有关自定义函数的所有帮助均不适用mutate
,但这似乎不一致,或者至少让我烦恼,因为我实现的解决方案的模拟是:
df_mean <- function(df) {
temp <- data.frame(mean = rep(mean(df$value), nrow(df)))
temp
}
df_ply_3 <- df
df_ply_3$mean <- ddply(df, .(id), df_mean)$mean
在线,看来我必须这样做:
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
为什么我不能使用mutate
具有自定义功能?难道只是“内置”函数返回某种类ddply
可以处理与必须踢出一个完整的data.frame
然后只调出我关心的栏目?
感谢您帮助我“得到它”!
@Gregor 回答后更新
很棒的答案,我想我现在明白了。我确实很困惑mutate
and summarize
意味着......认为他们是论据ddply
关于如何处理结果与实际情况being函数本身。所以,感谢您的深刻见解。
而且,它确实有助于理解这一点without mutate/summarize
,我需要返回一个data.frame
,这就是我必须这样做的原因cbind
具有列名称的列df
得到返回。
最后如果我do use mutate
,现在意识到我可以返回向量结果并获得正确的结果是有帮助的。于是,我can这样做,在阅读您的答案后我现在已经理解了:
# I also caught that the code above doesn't do the right thing
# and recycles the single value returned by mean() vs. repeating it like
# I expected. Now that I know it's taking a vector, I know I need to return
# a vector the same length as my mini df
custom_mean <- function(x) {
rep(mean(x), length(x))
}
df_ply_5 <- ddply(df, .(id), mutate,
mean = custom_mean(value))
再次感谢您的深入解答!
根据 @Gregor 的最后评论更新
嗯。我用了rep(mean(x), length(x))
由于这一观察df_ply_3
的结果(我承认当我第一次运行它时并没有仔细观察它,我只是看到它没有给我一个错误!):
df_mean <- function(x) {
data.frame(mean = mean(x$value))
}
df_ply_3 <- df
df_ply_3$mean <- ddply(df, .(id), df_mean)$mean
df_ply_3
id value mean
1 a 1 2
2 a 2 5
3 a 3 8
4 b 4 2
5 b 5 5
6 b 6 8
7 c 7 2
8 c 8 5
9 c 9 8
所以,我认为我的代码实际上是一个意外,因为我有 3id
变量重复 3 次。因此实际回报相当于summarize
(每行一行id
值),并进行回收。如果我像这样更新数据框,测试该理论似乎是准确的:
df <- data.frame(id = c(rep(letters[1:3], each = 3), "d"),
value = 1:10)
我在尝试使用时遇到错误df_ply_3
方法与df_mean()
:
Error in `$<-.data.frame`(`*tmp*`, "mean", value = c(2, 5, 8, 10)) :
replacement has 4 rows, data has 10
所以,迷你 df 传递给df_mean
返回一个df
where mean
是取平均值的结果,如果value
向量(返回一个值)。所以,我的输出只是一个data.frame
三个值,每个值一个id
团体。我在想mutate
有点“记住”它传递了一个迷你数据帧,然后重复单个输出以匹配它的长度?
无论如何,感谢您的评论df_ply_5
;事实上,如果我删除rep()
一点然后返回mean(x)
,效果很好!