【问题标题】:How do I create a function to mutate new columns with a variable name and "_pct"?如何创建一个函数来改变具有变量名和“_pct”的新列?
【发布时间】:2021-08-14 02:56:45
【问题描述】:

mtcars 为例。我想编写一个函数来创建countpct 列,如下所示-

library(tidyverse)

mtcars %>% 
  group_by(cyl) %>% 
  summarise(count = n()) %>% 
  ungroup() %>% 
  mutate(cyl_pct = count/sum(count))

这会产生输出 -

# A tibble: 3 x 3
    cyl count mpg_pct
  <dbl> <int>   <dbl>
1     4    11   0.344
2     6     7   0.219
3     8    14   0.438

但是,我想创建一个函数,我可以将group_by 列指定为任何列,mutate 列将命名为groub_by 中指定的列名和_pct。所以如果我想使用dispdisp 将是我的group_by 变量,并且该函数将改变一个disp_pct 列。

【问题讨论】:

  • @akrun 是的,错字。我将编辑问题。

标签: r tidyeval


【解决方案1】:

类似于 akrun 的回答,但使用 {{ 而不是 !!

foo = function(data, col) {
  data %>%
    group_by({{col}}) %>%
    summarize(count = n()) %>%
    ungroup %>% 
    mutate(
      "{{col}}_pct" := count / sum(count)
    )
}

foo(mtcars, cyl)
# `summarise()` ungrouping output (override with `.groups` argument)
# # A tibble: 3 x 3
#     cyl count cyl_pct
#   <dbl> <int>   <dbl>
# 1     4    11   0.344
# 2     6     7   0.219
# 3     8    14   0.438

【讨论】:

    【解决方案2】:

    假设输入未加引号,使用ensym 转换为符号,在group_by 内评估(!!),同时将符号转换为字符串(as_string)并粘贴前缀'_pct' 为新的列名。在mutate 中,我们可以使用:=!! 从创建的对象('colnm')中分配列名

    library(stringr)
    library(dplyr)
    f1 <- function(dat, grp) {
            grp <- ensym(grp)
            colnm <- str_c(rlang::as_string(grp), '_pct')
            dat %>%
               group_by(!!grp) %>%
               summarise(count = n(), .groups = 'drop') %>%
               mutate(!! colnm := count/sum(count))
         }
    

    -测试

    f1(mtcars, cyl)
    # A tibble: 3 x 3
    #    cyl count cyl_pct
    #  <dbl> <int>   <dbl>
    #1     4    11   0.344
    #2     6     7   0.219
    #3     8    14   0.438
    

    【讨论】:

      【解决方案3】:

      这可能与我亲爱的朋友@akrun 发布的没有什么不同。然而,在我的版本中,我使用了enquo 函数而不是ensym。 两者之间实际上存在细微差别,我想您可能有兴趣了解:

      • 根据nse-defuse 的文档,ensym 返回一个原始表达式,而enquo 返回一个“quosure”,它实际上是一个“包含表达式和环境的包装器”。所以我们需要一个额外的步骤来访问enquo的quosure表达式。
      • 在这种情况下,我们使用get_expr 来实现我们的目的。因此,这里只是编写此函数的另一个版本,我认为以后阅读这篇文章的人可能会对它感兴趣。
      library(dplyr)
      library(rlang)
      
      fn <- function(data, Var) {
        Var <- enquo(Var)
        colnm <- paste(get_expr(Var), "pct", sep = "_")
      
        data %>% 
          group_by(!!Var) %>% 
          summarise(count = n()) %>% 
          ungroup() %>% 
          mutate(!! colnm := count/sum(count))
      }
      
      fn(mtcars, cyl)
      
      # A tibble: 3 x 3
          cyl count cyl_pct
        <dbl> <int>   <dbl>
      1     4    11   0.344
      2     6     7   0.219
      3     8    14   0.438
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-22
        • 2018-05-29
        • 2015-05-07
        • 1970-01-01
        • 2021-02-14
        相关资源
        最近更新 更多