我ddply
经常使用,但从历史上讲summarize
(偶尔mutate
)仅使用基本功能(如mean()
,var1 - var2
等等)。我有一个数据集,我试图在其中应用自定义,参与程度更高的函数,并开始尝试研究如何使用ddply
。我有一个成功的解决方案,但是我不明白为什么它会像这样,而对于更多“常规”功能却如此。
有关的
这是一个示例数据集:
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
将其拆分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
和summarize
含义感到困惑……认为它们是ddply
关于如何处理结果与实际上是函数本身的争论。因此,感谢您的深刻见解。
另外,它确实有助于了解没有的情况 mutate/summarize
,我需要返回data.frame
,这就是我必须返回具有返回cbind
的列名称的列的df
原因。
最后,如果我做的使用mutate
,是有帮助的,现在意识到我可以返回一个向量结果,并得到正确的结果。因此,我可以做到这一点,阅读您的回答后,我现在已经明白了:
# 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
因此,我基于3个id
变量重复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
因此,传递给mini的dfdf_mean
返回一个df
where mean
,即value
取向量(取一个值)的平均值。因此,我的输出只是data.frame
三个值中的一个,id
每组一个。我在想mutate
某种方式“记住”它已传递一个小型数据帧,然后重复单个输出以匹配其长度?
无论如何,谢谢您的评论df_ply_5
;的确,如果我移开该rep()
位并返回mean(x)
,它的效果很好!
您基本上是对的。ddply
实际上,您可以根据石斑鱼将数据分解为微型数据帧,并对每个数据块都应用一个功能。
使用ddply
,所有工作都在数据帧中完成,因此.fun
参数必须将一个(小型)数据帧作为输入并返回一个数据帧作为输出。
mutate
并且summarize
是符合此要求的函数(它们接收并返回数据帧)。您可以查看他们的个人帮助页面,也可以在外部的数据框中运行它们ddply
,例如
mutate(mtcars, mean.mpg = mean(mpg))
summarize(mtcars, mean.mpg = mean(mpg))
如果您不使用mutate
或summarize
,即仅使用自定义函数,则您的函数还需要采用一个(小型)数据帧作为参数,然后返回一个数据帧。
如果您确实使用mutate
或summarize
,传递给您的任何其他函数ddply
都不会被使用ddply
,它们只会被传递给mutate
或使用summarize
。mutate
以及summarize
作用于数据列的函数,而不是作用于整个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))
这很好地扩展了,您可以具有接受多个参数的函数,并且可以为它们提供不同的列作为参数,但是如果使用mutate
或summarize
,则必须为其他函数提供参数;您不只是传递函数。
您似乎想传递ddply
一个已经“知道”平均值的函数。对于这一点,我认为你需要不使用mutate
或summarize
,但你可以砍你自己的版本。对于summarize
样的行为,返回data.frame相同的值,用于mutate
般的行为,你的额外的价值返还原物data.framecbind
上编
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)
为什么不能将mutate与自定义函数一起使用?仅仅是“内置”函数返回某种ddply可以处理的类,而必须踢出完整的data.frame然后仅调出我关心的列?
恰恰相反!mutate
并summarize
以数据帧作为输入,并踢出数据帧作为返回。但是,发生变异和总结是你传递到ddply的功能,并不意味着或任何其他。
Mutate和summary是便利功能,您将在99%的时间内使用ddply
。
如果您不使用mutate / summaryize,则您的函数需要获取并返回一个数据帧。
如果您确实使用了mutate / summitize,那么您就不会传递它们的功能,而是传递它们的表达式,这些表达式可以使用您的(小型)数据帧进行求值。如果是变异的,则返回值应该是要附加到数据的向量(必要时回收)。如果是汇总,则返回值应为单个值。您不会传递类似的函数mean
;您传递一个表达式,例如mean(mpg)
。
dplyr
呢这是以前写dplyr
的东西,或者至少是一件大事。dplyr
消除了此过程中的许多困惑,因为它实质上是用顺序函数(后跟或)替换ddply
withmutate
或summarize
as参数的嵌套。我的答案的版本是group_by
mutate
summarize
dplyr
library(dplyr)
group_by(mtcars, cyl) %>%
mutate(mean.mpg = mean(mpg))
将新的列创建直接传递给mutate
(或summarize
)后,就不会混淆哪个函数执行了什么操作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句