r语言 - dplyr::summarize()的不同部分是否可以有条件地计算



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

假设我正在处理iris数据并输出摘要,我只想包括Sepal的平均值。长度根据要求。我可以这样写:

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

但是有没有一种方法来实现管道中的条件,使它不需要被复制?

您可以使用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

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

这个技巧适用于数据。表,因为返回表达式是列表:

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()的简写。您可能有想要使用管道的理由,但我认为这个选项值得考虑。

关于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))} 
  }

略显俗气的方式:

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列。

相关内容

  • 没有找到相关文章

最新更新