可以有条件地计算dplyr :: summarize()的不同部分吗?

时间:2016-11-01 20:00:05

标签: r dplyr magrittr

是否可以让条件语句对dplyr :: summarize()的不同部分进行操作?

想象一下,我正在处理iris数据并输出摘要,并且我希望仅在请求时包含Sepal.Length的平均值。所以我可以这样做:

data(iris)
include_length = T
if (include_length) {
  iris %>% 
    group_by(Species) %>%
    summarize(mean_sepal_width = mean(Sepal.Width), mean_sepal_length = mean(Sepal.Length))
} else {
  iris %>% 
    group_by(Species) %>%
    summarize(mean_sepal_width = mean(Sepal.Width))

}

但是有没有办法在管道中实现条件,以便不需要重复?

4 个答案:

答案 0 :(得分:4)

您可以使用dplyr的SE函数的.dots参数以编程方式进行扩展,例如

library(dplyr)

take_means <- function(include_length){
    iris %>% 
        group_by(Species) %>%
        summarize_(mean_sepal_width = ~mean(Sepal.Width), 
                   .dots = if(include_length){
                       list(mean_sepal_length = ~mean(Sepal.Length))
                   })
}

take_means(TRUE)
#> # A tibble: 3 × 3
#>      Species mean_sepal_width mean_sepal_length
#>       <fctr>            <dbl>             <dbl>
#> 1     setosa            3.428             5.006
#> 2 versicolor            2.770             5.936
#> 3  virginica            2.974             6.588

take_means(FALSE)
#> # A tibble: 3 × 2
#>      Species mean_sepal_width
#>       <fctr>            <dbl>
#> 1     setosa            3.428
#> 2 versicolor            2.770
#> 3  virginica            2.974

答案 1 :(得分:3)

在基数R中,您可以执行c(x, if (d) y),并且根据d的值,您将获得结果中包含或排除的第二个元素。 xy可以是矢量或列表。

这个技巧在data.table中起作用,因为返回表达式是一个列表:

library(data.table)
f = function(d) data.table(iris)[, c(
  .(mw = mean(Sepal.Width)), 
  if(d) .(ml = mean(Sepal.Length))
), by=Species]

用法

> f(TRUE)
      Species    mw    ml
1:     setosa 3.428 5.006
2: versicolor 2.770 5.936
3:  virginica 2.974 6.588
> f(FALSE)
      Species    mw
1:     setosa 3.428
2: versicolor 2.770
3:  virginica 2.974

DT[...]内,.()list()的简写。你可能有理由想要打管道,但我认为这个选项值得考虑。

答案 2 :(得分:1)

关于conditional evaluation with magrittr

可能的解决方案:

library(magrittr)
library(dplyr)

data(iris)
include_length = T

iris %>%
  group_by(Species) %>%
  { if (include_length) {summarize(., mean_sepal_width = mean(Sepal.Width), mean_sepal_length = mean(Sepal.Length))} 
    else {summarize(., mean_sepal_width = mean(Sepal.Width))} 
  }

答案 3 :(得分:0)

略带hack的方式:

iris %>%
    group_by(Species) %>%
    summarise(mean_sepal_length=if(include_length) mean(Sepal.Length) else NA,
              mean_sepal_width=mean(Sepal.Width))

这将创建一个列为include_length == TRUE的列,否则为NA。如果这是一个问题,您可以在后处理中删除NA列。