【问题标题】:using stringr::str_detect to detect if a string appears after a character have appeared 4 times使用 stringr::str_detect 检测字符串是否在字符出现 4 次后出现
【发布时间】:2021-02-15 15:02:48
【问题描述】:

不确定我的问题措辞是否到位,但本质上是我想要做的。

数据示例:

Data <- c("NELIG_Q1_1_C1_A", "NELIG_N1_1_EG1_B", "NELIG_V2_1_NTH_C", "NELIG_Q2_1_C5_Q",
"NELIG_N1_1_C1_RA", "NELIG_Q1_1_EG1_QR", "NELIG_V2_1_NTH_PQ", "NELIG_N2_1_C5_PRQ")

我想对最后一组字母组合使用str_detect 进行过滤。在我正在寻找的字符串/模式之前总会有四个“_”,但在第四个“_”之后可能有许多不同的字母组合。在上面的例子中,我试图只检测字母“Q”。

如果我做一个简单的 Data2 &lt;- Data %&gt;% filter(str_detect(column, "Q")) 我会得到所有在字符串中任何位置都有 Q 的行。我如何告诉它只关注最后一部分?

【问题讨论】:

    标签: r stringr stringi


    【解决方案1】:

    如果目标是检测/匹配那些在最后一个_ 之后的“部分”中包含Q 的字符串,那么这可行:

    grep("_[A-Z]*Q[A-Z]*$", Data, value = T, perl = T)
    [1] "NELIG_Q2_1_C5_Q"   "NELIG_Q1_1_EG1_QR" "NELIG_V2_1_NTH_PQ" "NELIG_N2_1_C5_PRQ"
    

    或者,str_detect:

    library(stringr)
    str_detect(Data, "_[A-Z]*Q[A-Z]*$")
    [1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
    

    数据:

    Data <- c("NELIG_Q1_1_C1_A", "NELIG_N1_1_EG1_B", "NELIG_V2_1_NTH_C", "NELIG_Q2_1_C5_Q",
              "NELIG_N1_1_C1_RA", "NELIG_Q1_1_EG1_QR", "NELIG_V2_1_NTH_PQ", "NELIG_N2_1_C5_PRQ")
    

    【讨论】:

    • 这可能是我最喜欢的答案,因为它是使用 tidyverse 类型解决方案中最“严格”的。我只想了解 "_[az]*Q[az]* 中的方式/位置$" 它告诉它只搜索最后一部分?我知道我们说要检测 DATA 中的字符串,寻找以 _ 开头的字符串(有一个字符)**不确定 *Q 做什么**(后跟字符)** 不确定 *$ 做什么)跨度>
    • 正如你所说,_[a-z]*Q[a-z]*$ 捕获了最后一个“部分”,因为锚点 $。这是一个零宽度元字符,将模式锚定到字符串中的 position,即它的最后! (相反的锚点是^,它将模式与字符串的开头联系起来。)
    • 谢谢!这很有道理。
    【解决方案2】:

    如果你想使用 tidyverse:

    library(magrittr)
    
    data <- tibble::tibble(Col =  c("NELIG_Q1_1_C1_A", "NELIG_N1_1_EG1_B", 
                                    "NELIG_V2_1_NTH_C", "NELIG_Q2_1_C5_Q",
                                    "NELIG_N1_1_C1_RA", "NELIG_Q1_1_EG1_QR", 
                                    "NELIG_V2_1_NTH_PQ", "NELIG_N2_1_C5_PRQ"))
    
    data %>% 
      dplyr::mutate(Col = purrr::map_lgl(Col,
                                         ~ stringr::str_detect(
                                           unlist(
                                             stringr::str_split(.x, 
                                                                "_"))[5], 
                                           "Q")))
    #> # A tibble: 8 x 1
    #>   Col  
    #>   <lgl>
    #> 1 FALSE
    #> 2 FALSE
    #> 3 FALSE
    #> 4 TRUE 
    #> 5 FALSE
    #> 6 TRUE 
    #> 7 TRUE 
    #> 8 TRUE
    

    reprex package (v0.3.0) 于 2020-11-05 创建

    【讨论】:

      【解决方案3】:

      如果我正确理解您的问题,那么您可以这样做:

      library(stringr)
      str_detect(Data, ".*_.*_.*_.*_.*Q.*$")
      #R> [1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
      

      这将检测第四个“_”之后是否有任何“Q”。

      看标题:

      检测 4 个常量字符后的字符串

      然后你可以做一个这样的通用函数:

      # returns TRUE if a certain character occurs after a character has been 
      # there four times.
      # 
      # Args: 
      #   x characters to check.
      #   what character to occur at the end. 
      #   after character to occur four times.
      detect_after_four_times <- function(x, what, after){
        reg <- sprintf(".*%s.*%s.*%s.*%s.*%s.*$", after, after, after, after, 
                       what)
        str_detect(x, reg)
      }
      
      detect_after_four_times(Data, "Q", "_")
      #R> [1] FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
      detect_after_four_times(Data, "R", "_") # look for R instead
      #R> [1] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE
      
      # also works if there are only three times of "after"
      detect_after_four_times("only_three_dashes_Q", "Q", "_")
      #R> [1] FALSE
      

      【讨论】:

        猜你喜欢
        • 2021-01-21
        • 1970-01-01
        • 2019-10-30
        • 1970-01-01
        • 2019-12-03
        • 2015-05-11
        • 2012-06-05
        • 2015-03-03
        • 2017-02-23
        相关资源
        最近更新 更多