代码之家  ›  专栏  ›  技术社区  ›  conv3d

dplyr按列名称分组,列名称描述为字符串向量

  •  22
  • conv3d  · 技术社区  · 8 年前

    我试图在数据框中按多个列对\u进行分组,但我无法按函数写出group\u中的每个列名称,因此我想将这些列名称称为向量,如下所示:

    cols <- colnames(mtcars)[grep("[a-z]{3,}$", colnames(mtcars))]
    mtcars %>% filter(disp < 160) %>% group_by(cols) %>% summarise(n = n())
    

    这将返回错误:

    Error in mutate_impl(.data, dots) : 
      Column `mtcars[colnames(mtcars)[grep("[a-z]{3,}$", colnames(mtcars))]]` must be length 12 (the number of rows) or one, not 7
    

    我当然想使用dplyr函数来实现这一点,但我想不出这一点。

    2 回复  |  直到 8 年前
        1
  •  40
  •   akuiper    8 年前

    您可以使用 group_by_at ,其中可以将列名的字符向量作为组变量传递:

    mtcars %>% 
        filter(disp < 160) %>% 
        group_by_at(cols) %>% 
        summarise(n = n())
    # A tibble: 12 x 8
    # Groups:   mpg, cyl, disp, drat, qsec, gear [?]
    #     mpg   cyl  disp  drat  qsec  gear  carb     n
    #   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
    # 1  19.7     6 145.0  3.62 15.50     5     6     1
    # 2  21.4     4 121.0  4.11 18.60     4     2     1
    # 3  21.5     4 120.1  3.70 20.01     3     1     1
    # 4  22.8     4 108.0  3.85 18.61     4     1     1
    # ...
    

    或者可以将列选择移动到内部 group\u by\u at 使用 vars 和列选择辅助函数:

    mtcars %>% 
        filter(disp < 160) %>% 
        group_by_at(vars(matches('[a-z]{3,}$'))) %>% 
        summarise(n = n())
    
    # A tibble: 12 x 8
    # Groups:   mpg, cyl, disp, drat, qsec, gear [?]
    #     mpg   cyl  disp  drat  qsec  gear  carb     n
    #   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int>
    # 1  19.7     6 145.0  3.62 15.50     5     6     1
    # 2  21.4     4 121.0  4.11 18.60     4     2     1
    # 3  21.5     4 120.1  3.70 20.01     3     1     1
    # 4  22.8     4 108.0  3.85 18.61     4     1     1
    # ...
    
        2
  •  19
  •   Harrison Jones    6 年前

    我相信 group_by_at 现在已被以下组合所取代 group_by across . 和 summarise 有一个实验 .groups 参数,从中可以选择创建摘要对象后如何处理分组。这里有一个可供考虑的替代方案:

    cols <- colnames(mtcars)[grep("[a-z]{3,}$", colnames(mtcars))]
    
    original <- mtcars %>% 
      filter(disp < 160) %>% 
      group_by_at(cols) %>% 
      summarise(n = n())
    
    superseded <- mtcars %>%
      filter(disp < 160) %>%
      group_by(across(all_of(cols))) %>%
      summarise(n = n(), .groups = 'drop_last')
    
    all.equal(original, superseded)
    

    下面是一篇博客文章,详细介绍了如何使用 穿过 功能: https://www.tidyverse.org/blog/2020/04/dplyr-1-0-0-colwise/

    推荐文章