【问题标题】:tidy eval map over column names列名上的整洁 eval 映射
【发布时间】:2023-04-05 16:33:01
【问题描述】:

我自己做了如下函数:

    emp_term_var <- function(data, colName, year = "2015") {
  
  # Terminations by year and variable in df
  colName <- enquo(colName) 
  term_test <- data %>%
    filter(year(DateofTermination) == year) %>%
    group_by(UQ(colName)) %>%
    count(UQ(colName)) %>%
    clean_names()
  return(term_test)
  
}

我有一个包含多个列的 df,例如部门、州、职位等。当我想使用我编写的函数时,我将不带引号的列名称如下:

emp_term_var(data = df, colName = Department, year = "2015")

返回:

# A tibble: 5 x 2
# Groups:   department [5]
  department               n
  <chr>                <int>
1 Admin Offices            1
2 IT/IS                    4
3 Production              15
4 Sales                    1
5 Software Engineering     2
> 

如何映射多个列?如果我尝试

columns <- c(Department, State)

R 不允许我这样做,因为它将这些标识为对象而不是列名。如何让 R 知道这些是要存储在对象列中的列名,以便我可以以这种形式将其传递给映射:

map(colnames, ~ emp_term_var(df, colName = .x, year = "2015"))

【问题讨论】:

    标签: r tidyverse purrr tidyeval


    【解决方案1】:

    另一个解决方案是保持你的函数不变,但改变你在map()中调用它的方式:

    columns <- c("Department", "State")
    
    map(colnames, ~ emp_term_var(df, colName = .data[[.x]], year = "2015"))
    

    注意我们如何传递 colName = .data[[.x]] 而不是 colName = .x

    您也可以在其他上下文中执行此操作,例如 for 循环:

    for (col in columns) {
      print(
        emp_term_var(df, colName = .data[[col]], year = "2015")
      )
    }
    

    【讨论】:

      【解决方案2】:

      不要使用 enquo 将其更改为 .data 或使用 ensym 转换为符号并计算 (!!)

      emp_term_var <- function(data, colName, year = "2015") {
        
        # Terminations by year and variable in df
        colName <- ensym(colName) 
        term_test <- data %>%
          filter(year(DateofTermination) == year) %>%
          #group_by(!!colName)) %>%
          count(!!(colName)) %>%
          clean_names()
        return(term_test)
        
      }
      

      注意:count 也可以在没有任何分组的情况下使用该列

      ensym 路由的优点是它可以引用和不带引号的输入,即将字符串作为列名并且不带引号

      nm1 <- c("Department", "State")
      purrr::map(nm1, ~ emp_term_var(df, colName = !!.x, year = "2015"))
      

      或者如果我们想使用

      emp_term_var(data = df, colName = Department, year = "2015")
      

      或者可以带

      emp_term_var(data = df, colName = "Department", year = "2015")
      

      【讨论】:

      • 非常感谢您的支持我学到了很多:)
      • 嗨,阿克伦。我看到您经常提到引用和未引用的输入作为ensym() 的优势。 ensym()确实复制了=的LHS接口,其中foo = bar"foo" = bar都允许。然而,这有一个缺点,提供带引号的输入可能会给人一种错误的印象,即参数不是数据屏蔽的,您可以提供一个普通变量。我只会使用带有非语法名称的引号,例如"foo bar !"。我想我的观点是,我认为最好不要提及这个“功能”,因为它可能会产生误导。
      • Akrun,您的帖子启发了我寻找更好的解决方案:github.com/r-lib/rlang/issues/1300
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-19
      • 2016-05-15
      • 2017-06-03
      • 2015-03-12
      • 1970-01-01
      相关资源
      最近更新 更多