如何通过一个匿名函数来dplyr总结
问题描述:
我有3列一个简单的数据帧:名,目标,并实际。 因为这是一个大得多的数据框的简化,我想用dplyr来计算每个人满足目标的次数。如何通过一个匿名函数来dplyr总结
df <- data.frame(name = c(rep('Fred', 3), rep('Sally', 4)),
goal = c(4,6,5,7,3,8,5), actual=c(4,5,5,3,3,6,4))
结果应该是这样的:
我应该能够通过类似于如下所示的匿名功能,但不具备语法非常正确:
library(dplyr)
g <- group_by(df, name)
summ <- summarise(g, met_goal = sum((function(x,y) {
if(x>y){return(0)}
else{return(1)}
})(goal, actual)
)
)
当运行上述代码中,我看到这些错误的3:
警告消息: 1:在如果(X == y)的{: 条件具有长度> 1且仅第一元件将可以采用使用
data.table
答
我们在goal
和actual
长度相等的载体,所以关系运算符是合适用在这里。但是,当我们在简单的if()
声明中使用它们时,我们可能会得到意想不到的结果,因为if()
需要长度为1的向量。由于我们有相等的长度向量,并且我们需要一个二进制结果,所以采用逻辑向量的总和是最好的方法,如下所示。因为你想0
为goal > actual
和1
否则
group_by(df, name) %>%
summarise(met_goal = sum(goal <= actual))
# A tibble: 2 x 2
name met_goal
<fctr> <int>
1 Fred 2
2 Sally 1
操作切换到<=
。
请注意,您可以使用使用匿名函数。这是if()
声明抛弃了你。例如,使用
sum((function(x, y) x <= y)(goal, actual))
将以您询问的方式工作。
答
解决方案:
你问dplyr
的解决方案,但实际的数据要大的多,你可以使用data.table
。 foo
是您想要应用的功能。
foo <- function(x, y) {
res <- 0
if (x <= y) {
res <- 1
}
return(res)
}
library(data.table)
setDT(df)
setkey(df, name)[, foo(goal, actual), .(name, 1:nrow(df))][, sum(V1), name]
如果你喜欢的管道,那么你可以使用这个:
library(magrittr)
setDT(df) %>%
setkey(name) %>%
.[, foo(goal, actual), .(name, 1:nrow(.))] %>%
.[, .(met_goal = sum(V1)), name]
name met_goal
1: Fred 2
2: Sally 1
+0
我对数据表没有太多的工作,但我知道他们的好处,所以我相信我会在将来使用类似的东西。 –
这很好地回答了问题。我故意做了过于复杂的尝试,因为我想看看更复杂/一般的匿名函数是如何传递的。 –
@MichaelSzczepaniak - 请注意,您*可以*使用匿名功能。这是'if()'声明让你失望。例如,sum((function(x,y)x
这完全是我在找的东西。感谢您解释这个(两次;-)。 –