【问题标题】:Detect multiple strings with dplyr and stringr使用 dplyr 和 stringr 检测多个字符串
【发布时间】:2014-12-26 20:38:38
【问题描述】:

我正在尝试结合 dplyr 和 stringr 来检测数据帧中的多个模式。我想使用 dplyr,因为我想测试许多不同的列。

以下是一些示例数据:

test.data <- data.frame(item = c("Apple", "Bear", "Orange", "Pear", "Two Apples"))
fruit <- c("Apple", "Orange", "Pear")
test.data
        item
1      Apple
2       Bear
3     Orange
4       Pear
5 Two Apples

我想使用的是这样的:

test.data <- test.data %>% mutate(is.fruit = str_detect(item, fruit))

并接收

        item is.fruit
1      Apple        1
2       Bear        0
3     Orange        1
4       Pear        1
5 Two Apples        1

一个非常简单的测试工作

> str_detect("Apple", fruit)
[1]  TRUE FALSE FALSE
> str_detect("Bear", fruit)
[1] FALSE FALSE FALSE

但即使没有 dplyr,我也无法让它在数据框的列上工作:

> test.data$is.fruit <- str_detect(test.data$item, fruit)
Error in check_pattern(pattern, string) : 
  Lengths of string and pattern not compatible

有人知道怎么做吗?

【问题讨论】:

    标签: r dplyr stringr


    【解决方案1】:

    str_detect 只接受长度为 1 的模式。使用paste(..., collapse = '|') 或使用any 将其转换为一个正则表达式:

    sapply(test.data$item, function(x) any(sapply(fruit, str_detect, string = x)))
    # Apple       Bear     Orange       Pear Two Apples
    #  TRUE      FALSE       TRUE       TRUE       TRUE
    
    str_detect(test.data$item, paste(fruit, collapse = '|'))
    # [1]  TRUE FALSE  TRUE  TRUE  TRUE
    

    【讨论】:

      【解决方案2】:

      这种简单的方法适用于精确匹配:

      test.data %>% mutate(is.fruit = item %in% fruit)
      # A tibble: 5 x 2
              item is.fruit
             <chr>    <lgl>
      1      Apple     TRUE
      2       Bear    FALSE
      3     Orange     TRUE
      4       Pear     TRUE
      5 Two Apples    FALSE
      

      这种方法适用于部分匹配(这是提出的问题):

      test.data %>% 
      rowwise() %>% 
      mutate(is.fruit = sum(str_detect(item, fruit)))
      
      Source: local data frame [5 x 2]
      Groups: <by row>
      
      # A tibble: 5 x 2
              item is.fruit
             <chr>    <int>
      1      Apple        1
      2       Bear        0
      3     Orange        1
      4       Pear        1
      5 Two Apples        1
      

      【讨论】:

      • 这仅适用于完全匹配的情况,在这种情况下使用str_detect 而不是==in 是多余的。
      • 啊,你说得对,亚历克斯。我猜我读的有点快。我已经更新了答案。
      【解决方案3】:

      使用 purrr 中的 map 函数可以进一步简化这一点,以便在管道和格式控制中使用 - map_int 返回数字,map_lgl 返回逻辑。

      library(purrr)
      
      test.data %>%
          mutate(is.fruit = map_int(item, ~any(str_detect(., fruit))))
      
              item is.fruit
      1       Apple     1
      2        Bear     0
      3      Orange     1
      4        Pear     1
      5  Two Apples     1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-23
        • 1970-01-01
        • 1970-01-01
        • 2017-11-04
        • 1970-01-01
        • 2021-02-15
        • 2021-01-21
        • 2019-11-14
        相关资源
        最近更新 更多