代码之家  ›  专栏  ›  技术社区  ›  Justin Landis

dplyr group_by function arguments非字符串

  •  -1
  • Justin Landis  · 技术社区  · 6 年前

    dplyr's vignette dplyr enquos ... 以将多个参数传递给group\by。

    一个简单的例子来说明它是如何工作的

    grp <- rlang::enquos(...)
    df %>%
        group_by(!!!grp)
    

    我不知道是否有一种方法可以在不保留 ...

    要了解调用的内容,请使用以下示例:

    #reproducable data
    df <- datasets::USJudgeRatings
    df$name <- rownames(df)
    df <- tidyr::gather(df, key = "key", value = "value", -name)
    df$dummy <- c("1","2")
    
    
    test_summarize <- function(df, sum.col, grp = NULL, filter = NULL) {
      filter <- rlang::enquo(filter)
      sum.col <- rlang::enquo(sum.col)
      if(!is.null(rlang::get_expr(filter))){
        df <- dplyr::filter(df, !!filter)
      }
    
      #how grp is turned into a character vector to be passed to .dots in group_by
      grp <- substitute(grp)
      if(!is.null(grp)){
        grp <- deparse(grp)
        grp <- strsplit(gsub(pattern = "list\\(|c\\(|\\)|", replacement = "", x = grp), split =",")[[1]]
        grp <- gsub(pattern = "^ | $", replacement = "", x = grp)
       df %>%
          dplyr::group_by(.dots=grp) %>%
          dplyr::summarise(mean = mean(!!sum.col), sum = sum(!!sum.col), n = n())
      } else{
        df %>%
          dplyr::summarise(mean = mean(!!sum.col), sum = sum(!!sum.col), n = n())
      }
    
    }
    
    test_summarize(df, sum.col=value, grp = c(name, dummy))
    
    # A tibble: 86 x 5
    # Groups:   name [?]
       name           dummy  mean   sum     n
       <chr>          <fct> <dbl> <dbl> <int>
     1 AARONSON,L.H.  1      7.17  43       6
     2 AARONSON,L.H.  2      7.42  44.5     6
     3 ALEXANDER,J.M. 1      8.35  50.1     6
     4 ALEXANDER,J.M. 2      7.95  47.7     6
     5 ARMENTANO,A.J. 1      7.53  45.2     6
     6 ARMENTANO,A.J. 2      7.7   46.2     6
     7 BERDON,R.I.    1      8.67  52       6
     8 BERDON,R.I.    2      8.25  49.5     6
     9 BRACKEN,J.J.   1      5.65  33.9     6
    10 BRACKEN,J.J.   2      5.82  34.9     6
    # ... with 76 more rows
    

    grp enquos(...) 失败了,所以我做了一个深入处理,把它们变成了一个字符向量,老实说,我应该只希望用户传递字符?

    0 回复  |  直到 6 年前
        1
  •  1
  •   akrun    6 年前

    如果我们使用 group_by_at ,我们可能不需要 if/else 论点

    test_summarize <- function(df, sum.col, grp = NULL, filter = NULL) {
    df %>% 
         group_by_at(grp) %>%
         summarise(mean = mean({{sum.col}}), 
                   sum = sum({{sum.col}}), n = n())
    
       }
    
    
    test_summarize(df, sum.col=value, grp = c("name", "dummy"))
    # A tibble: 86 x 5
    # Groups:   name [43]
    #   name           dummy  mean   sum     n
    #   <chr>          <chr> <dbl> <dbl> <int>
    # 1 AARONSON,L.H.  1      7.17  43       6
    # 2 AARONSON,L.H.  2      7.42  44.5     6
    # 3 ALEXANDER,J.M. 1      8.35  50.1     6
    # 4 ALEXANDER,J.M. 2      7.95  47.7     6
    # 5 ARMENTANO,A.J. 1      7.53  45.2     6
    # 6 ARMENTANO,A.J. 2      7.7   46.2     6
    # 7 BERDON,R.I.    1      8.67  52       6
    # 8 BERDON,R.I.    2      8.25  49.5     6
    # 9 BRACKEN,J.J.   1      5.65  33.9     6
    #10 BRACKEN,J.J.   2      5.82  34.9     6
    # … with 76 more rows
    
    
    
    test_summarize(df, sum.col=value)
    # A tibble: 1 x 3
    #   mean   sum     n
    #  <dbl> <dbl> <int>
    #1  7.57 3908.   516
    

    df %>%
       summarise(mean = mean(value), sum = sum(value), n = n())
    #     mean    sum   n
    #1 7.57345 3907.9 516
    

    如果我们使用 filter ,那么一个选择是 ... 通过尽可能多的过滤条件

    test_summarize <- function(df, sum.col, grp = NULL, ...) {
        df %>% 
             filter(!!! rlang::enexprs(...)) %>%
             group_by_at(grp) %>%
             summarise(mean = mean({{sum.col}}), sum = sum({{sum.col}}), n = n())
    
    }
    
    
    test_summarize(df, sum.col=value, grp = c("name", "dummy"),
            key %in% c("CONT", "INTG"), value > 6.5)
    # A tibble: 77 x 5
    # Groups:   name [43]
    #   name           dummy  mean   sum     n
    #   <chr>          <chr> <dbl> <dbl> <int>
    # 1 AARONSON,L.H.  2       7.9   7.9     1
    # 2 ALEXANDER,J.M. 1       8.9   8.9     1
    # 3 ALEXANDER,J.M. 2       6.8   6.8     1
    # 4 ARMENTANO,A.J. 1       7.2   7.2     1
    # 5 ARMENTANO,A.J. 2       8.1   8.1     1
    # 6 BERDON,R.I.    1       8.8   8.8     1
    # 7 BERDON,R.I.    2       6.8   6.8     1
    # 8 BRACKEN,J.J.   1       7.3   7.3     1
    # 9 BURNS,E.B.     1       8.8   8.8     1
    #10 CALLAHAN,R.J.  1      10.6  10.6     1
    # … with 67 more rows
    

    当没有过滤器参数时,它也会计算

    test_summarize(df, sum.col=value, grp = c("name", "dummy"))
    # A tibble: 86 x 5
    # Groups:   name [43]
    #   name           dummy  mean   sum     n
    #   <chr>          <chr> <dbl> <dbl> <int>
    # 1 AARONSON,L.H.  1      7.17  43       6
    # 2 AARONSON,L.H.  2      7.42  44.5     6
    # 3 ALEXANDER,J.M. 1      8.35  50.1     6
    # 4 ALEXANDER,J.M. 2      7.95  47.7     6
    # 5 ARMENTANO,A.J. 1      7.53  45.2     6
    # 6 ARMENTANO,A.J. 2      7.7   46.2     6
    # 7 BERDON,R.I.    1      8.67  52       6
    # 8 BERDON,R.I.    2      8.25  49.5     6
    # 9 BRACKEN,J.J.   1      5.65  33.9     6
    #10 BRACKEN,J.J.   2      5.82  34.9     6
    # … with 76 more rows