【问题标题】:how to use str_detect within across when searching multiple columns for several search strings在为多个搜索字符串搜索多个列时如何在其中使用 str_detect
【发布时间】:2021-07-28 06:42:34
【问题描述】:

我希望将我的函数迁移到新创建的 across

我使用filter_at 在多个列中搜索多个关键字的函数。

但是,我正在努力使用across 复制它,如下所示:

library(tidyverse)

raw_df <- tibble::tribble(
  ~cust_name, ~other_desc, ~trans, ~val,
     "Cisco",   "nothing",    "a", 100L,
    "bad_cs",     "cisCo",    "s", 101L,
       "Ibm",   "nothing",    "d", 102L,
    "bad_ib",       "ibM",    "f", 102L,
    "oraCle",    "Oracle",    "g", 103L,
      "mSft",   "nothing",    "k", 103L,
      "noth",      "Msft",    "j", 104L,
      "noth",    "oracle",    "l", 104L
  )


search_string = c("ibm", "cisco")


# Done using `filter_at`
raw_df %>% 
  filter_at(.vars = vars(cust_name, other_desc),
            .vars_predicate = any_vars(str_detect(., regex(paste(search_string, collapse = "|"), ignore_case = TRUE)))
            
  ) %>% unique()
  
  
# Not able to replicate result with `across`
raw_df %>% 
  filter(across(
    .cols = c(cust_name, other_desc), 
    .fns = ~str_detect(.), regex(paste(search_string, collapse = "|"), ignore_case = TRUE)))



raw_df %>% 
  filter(str_detect,
         across(any_of(cust_name, other_desc),
         regex(paste(search_string, collapse = "|"), ignore_case = TRUE)))

【问题讨论】:

    标签: r across


    【解决方案1】:

    acrossReduce 组合以选择出现任何模式的行。

    library(dplyr)
    library(stringr)
    
    pat <- paste(search_string, collapse = "|")
    
    raw_df %>% 
      filter(Reduce(`|`, across(c(cust_name, other_desc), 
            ~str_detect(., regex(pat, ignore_case = TRUE)))))
    

    但是,我认为在这里使用 if_any 更合适,因为它是为处理此类情况而构建的 -

    raw_df %>%
      filter(if_any(c(cust_name, other_desc), 
                    ~str_detect(., regex(pat, ignore_case = TRUE))))
    
    # cust_name other_desc trans   val
    #  <chr>     <chr>      <chr> <int>
    #1 Cisco     nothing    a       100
    #2 bad_cs    cisCo      s       101
    #3 Ibm       nothing    d       102
    #4 bad_ib    ibM        f       102
    

    【讨论】:

      【解决方案2】:

      虽然可以使用 Ronak 的解决方案:

      这是一个带有附加技巧的替代方案。我认为这是if_any 所做的: 使用rowSums

      rowAny <- function(x) rowSums(x) > 0 
      
      
      raw_df %>% 
          filter(rowAny(
              across(
                  .cols = c(cust_name, other_desc),
                  .fns = ~ str_detect(., regex("ibm|cisco", ignore_case = TRUE))
              )))
      

      输出:

        cust_name other_desc trans   val
        <chr>     <chr>      <chr> <int>
      1 Cisco     nothing    a       100
      2 bad_cs    cisCo      s       101
      3 Ibm       nothing    d       102
      4 bad_ib    ibM        f       102
      

      【讨论】:

      • 您能解释一下rowSumsfilter 中的工作原理吗
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-16
      • 2011-11-20
      • 1970-01-01
      相关资源
      最近更新 更多