【问题标题】:Pass argument to a function containing dplyr piped expression group_by with stringr::str_extract使用 stringr::str_extract 将参数传递给包含 dplyr 管道表达式 group_by 的函数
【发布时间】:2020-04-30 05:29:00
【问题描述】:

我想根据子字符串分组总结以下数据:

df <- tribble(
  ~sometext, ~somevalue,
  "Kardiochirurgia",  120,
  "Kardiologia",      240,
  "Ortopedia onkologiczna",        120,
  "Kardiochirurgia onkologiczna", 300,
  "Ortopedia i traumatologia",110,
  "Urologia", 80
)

这是我想要分组的子字符串:

categories <- c("kardio","orto", "uro")

以下代码有效,我会反复使用,所以我想把它变成一个函数:

df %>% 
  group_by(categories=
    str_extract(
      string = str_to_lower(.$sometext),
      pattern = paste0(categories, collapse="|"))) %>% 
  summarise(somevalue = sum(somevalue))

脚本完全符合我的预期:

# # A tibble: 3 x 2
# categories somevalue
# <chr>          <dbl>
# 1 kardio           660
# 2 orto             230
# 3 uro               80

我把它变成一个函数后,它不起作用:

group_by_str <- function(df, strings, patterns) {
  df %>% 
    group_by(categories=
               str_extract(
                 string = str_to_lower(.[,{{strings}}]),
                 pattern = paste0(patterns, collapse="|"))) 
   return(df)
}

双括号字符串是我的尝试之一,我首先尝试不使用,尝试传递带引号的名称等但无济于事。 尝试在数据集上使用它:

df %>% group_by_str(strings=sometext, patterns= categories) %>% summarise(somevalue = sum(somevalue))

返回错误,显然它不知道'strings'是包含字符串的列的名称。在这种情况下,将列名传递给函数的正确方法应该是什么?

错误消息表明 R 可以看到列的内容并尝试将其视为列名:

 Error: Can't find columns `Kardiochirurgia`, `Kardiologia`, `Ortopedia onkologiczna`, `Kardiochirurgia onkologiczna`, `Ortopedia i traumatologia`, … (and 1 more) in `.data`.
Run `rlang::last_error()` to see where the error occurred. 

如果我删除大括号,则错误提示 R 在 DF 中看不到 sometext 列名:

Error in check_names_df(j, x) : object 'sometext' not found

【问题讨论】:

    标签: r dplyr tidyverse rlang


    【解决方案1】:

    通过一些修改,我们可以使用下面的代码。

    1. 我们不需要评估patterns(添加这一点是因为我也想到了tidyevaluating patterns)。

    2. 我们可以评估strings{{}}rlang >=0.4.0

    3. 我们不需要return 声明

    4. 我们可以在函数内部做所有事情(包括摘要)

    修改代码:

    group_by_str <- function(df, strings, patterns) {
      df %>% 
        group_by(categories=
                   str_extract(
                     string = str_to_lower({{strings}}),
                     pattern = paste0(patterns, 
                                              collapse="|"))) %>%
    
        summarise(somevalue = sum(somevalue)) 
    
    } 
    
    
      group_by_str(df,strings=sometext, patterns= categories) 
    

    管道友好:

     df %>% 
      group_by_str(strings=sometext, patterns= categories)
    

    结果:

    # A tibble: 3 x 2
      categories somevalue
      <chr>          <dbl>
    1 kardio           660
    2 orto             230
    3 uro               80
    

    【讨论】:

    • 有 rlang 1.0.0 吗? - 我想在这里走私非常感谢您的帮助。
    • 啊,哦不!我把版本误认为是tidyr。实际上是rlang 0.4.2。 {{}}“技巧”是在 0.4.0 中引入的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2019-03-20
    • 1970-01-01
    • 2018-05-15
    • 2018-09-08
    相关资源
    最近更新 更多