【问题标题】:Can I use summarise_at for existing variables while adding other variables at the same time?我可以在添加其他变量的同时对现有变量使用 summarise_at 吗?
【发布时间】:2020-03-12 03:01:55
【问题描述】:

假设我有一个分组数据框:

> mtcars %>% 
+   group_by(cyl) %>% 
+   summarise(blah = mean(disp))
# A tibble: 3 x 2
    cyl  blah
  <dbl> <dbl>
1     4  105.
2     6  183.
3     8  353.

然后假设我想总结一些现有的变量:

> mtcars %>% 
+   group_by(cyl) %>% 
+   summarise_at(vars(vs:carb), sum)
# A tibble: 3 x 5
    cyl    vs    am  gear  carb
  <dbl> <dbl> <dbl> <dbl> <dbl>
1     4    10     8    45    17
2     6     4     3    27    24
3     8     0     2    46    49

但是,如果我想将两个汇总命令一起添加,我不能:

> mtcars %>% 
+   group_by(cyl) %>% 
+   summarise_at(vars(vs:carb), sum) %>% 
+   summarise(blah = mean(disp))
Error in mean(disp) : object 'disp' not found

在 dplyr 链中使用 group_by() 后,如何使用 summarise() 添加新功能以及使用 summarise_at(vars(vs:carb), sum) 对上述现有功能求和?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我能想到的唯一方法(目前)是在您的第一个摘要之前立即存储数据,然后运行两个摘要动词,并将它们加入分组变量。例如:

    library(dplyr)
    
    grouped_data <- group_by(mtcars, cyl)
    left_join(
      summarize(grouped_data, blah = mean(disp)),
      summarize_at(grouped_data, vars(vs:carb), sum),
      by = "cyl")
    # # A tibble: 3 x 6
    #     cyl  blah    vs    am  gear  carb
    #   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    # 1     4  105.    10     8    45    17
    # 2     6  183.     4     3    27    24
    # 3     8  353.     0     2    46    49
    

    【讨论】:

    • 比我的回答好,我需要两个group_by
    【解决方案2】:

    您可以使用summarise 产生的数据框left_join

    library(dplyr)
    
    data(mtcars)
    
    mtcars %>% 
      group_by(cyl) %>% 
      summarise_at(vars(vs:carb), sum) %>% 
      left_join(mtcars %>% group_by(cyl) %>% summarise(blah = mean(disp)))
    #Joining, by = "cyl"
    ## A tibble: 3 x 6
    #    cyl    vs    am  gear  carb  blah
    #  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    #1     4    10     8    45    17  105.
    #2     6     4     3    27    24  183.
    #3     8     0     2    46    49  353.
    

    【讨论】:

      【解决方案3】:

      我要做的是第一步使用mutate_at,这样其他列就不会折叠,然后将summarise_atmean一起用于所有列。

      library(dplyr) 
      
      mtcars %>% 
         group_by(cyl) %>% 
         mutate_at(vars(vs:carb), sum) %>%
         summarise_at(vars(vs:carb, disp), mean)
      
      #    cyl    vs    am  gear  carb  disp
      #  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
      #1     4    10     8    45    17  105.
      #2     6     4     3    27    24  183.
      #3     8     0     2    46    49  353.
      

      【讨论】:

        【解决方案4】:

        这是一种方法,我们需要先定义一个辅助函数,它只能在管道链中工作,并使用 dplyr 中未导出的函数,尽管有一天可能会中断。

        .at <- function(.vars, .funs, ...) {
          # make sure we are in a piped call
          in_a_piped_fun <- exists(".",parent.frame()) &&
            length(ls(envir=parent.frame(), all.names = TRUE)) == 1
          if (!in_a_piped_fun)
            stop(".at() must be called as an argument to a piped function")
          # borrow code from summarize_at
          .tbl <- try(eval.parent(quote(.)))
          dplyr:::manip_at(
            .tbl, .vars, .funs, rlang::enquo(.funs), rlang:::caller_env(),
            .include_group_vars = TRUE, ...)
        }
        
        library(dplyr, warn.conflicts = FALSE)
        mtcars %>%
          summarize(!!!.at(vars(vs:carb), sum),  blah = mean(disp))
        #>   vs am gear carb     blah
        #> 1 14 13  118   90 230.7219
        

        reprex package (v0.3.0) 于 2019 年 11 月 17 日创建

        【讨论】:

          猜你喜欢
          • 2022-01-22
          • 1970-01-01
          • 2018-02-21
          • 2019-05-30
          • 1970-01-01
          • 1970-01-01
          • 2014-10-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多