如何通过一个匿名函数来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)) 

enter image description here

结果应该是这样的:

enter image description here

我应该能够通过类似于如下所示的匿名功能,但不具备语法非常正确:

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

我们在goalactual长度相等的载体,所以关系运算符是合适用在这里。但是,当我们在简单的if()声明中使用它们时,我们可能会得到意想不到的结果,因为if()需要长度为1的向量。由于我们有相等的长度向量,并且我们需要一个二进制结果,所以采用逻辑向量的总和是最好的方法,如下所示。因为你想0goal > actual1否则

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

将以您询问的方式工作。

+0

这很好地回答了问题。我故意做了过于复杂的尝试,因为我想看看更复杂/一般的匿名函数是如何传递的。 –

+1

@MichaelSzczepaniak - 请注意,您*可以*使用匿名功能。这是'if()'声明让你失望。例如,sum((function(x,y)x

+1

这完全是我在找的东西。感谢您解释这个(两次;-)。 –

解决方案:

你问dplyr的解决方案,但实际的数据要大的多,你可以使用data.tablefoo是您想要应用的功能。

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

我对数据表没有太多的工作,但我知道他们的好处,所以我相信我会在将来使用类似的东西。 –