【问题标题】:If else statements to check if a string contains a substring in RIf else语句检查字符串是否包含R中的子字符串
【发布时间】:2018-06-12 14:12:25
【问题描述】:

我有一个列表,其中包含每个观察的多个字符串(见下文)。

  [1] A, C, D 
  [2] P, O, E
  [3] W, E, W
  [4] S, B, W

我想测试字符串是否包含某些子字符串,如果是,则返回相应的子字符串,在此示例中,这将是“A”或“B”(请参阅​​下面的所需结果)。每个观察将仅包含 2 个子字符串之一 (A|B)

  [1] A 
  [2] NA
  [3] NA
  [4] B

不,我已经尝试过解决它,但它似乎效率很低,而且我也没有让它工作。我该如何解决?

  if (i == "A") {
    type <- "A"
  } else if { (i == "B") 
    type <- "B" 
  } else { type <- "NA"
  } 

注意:我需要循环超过 1000 个观察结果

【问题讨论】:

  • 您可以使用grepl 查找包含您要查找的字母的字符串。对于每个字符串,你可以使用regexecregmatches 来返回模式(如果有的话)。

标签: r regex if-statement stringr


【解决方案1】:

假设您有一个字符向量,您可以为此目的使用stringr::str_extract

s <- c('A, C, D', 'P, O, E', 'W, E, W', 'S, B, W')
s
# [1] "A, C, D" "P, O, E" "W, E, W" "S, B, W"
stringr::str_extract(s, 'A|B')
# [1] "A" NA  NA  "B"

如果首选单词匹配,请使用单词边界\\b

stringr::str_extract(s, '\\b(A|B)\\b')
# [1] "A" NA  NA  "B"

如果子字符串由", "定义,你可以使用这个正则表达式(?&lt;=^|, )(A|B)(?=,|$)

# use the test case from G.Grothendieck
stringr::str_extract(c("A.A, C", "D, B"), '(?<=^|, )(A|B)(?=,|$)')
# [1] NA  "B"

【讨论】:

  • 工作完美,工作效率很高,谢谢!
  • 如果字符串可以是彼此的子字符串,则可能给出错误答案,例如例如s &lt;- c("AA, C", "D, B").
  • @G.Grothendieck 是的。但我认为情况取决于您想要的输出,更短或更长。并且按照长度对模式进行排序应该可以处理它。
  • 在我评论的示例中,它给出了 c("A", "B") 但正确答案是 c(NA, "B")
  • @G.Grothendieck 添加了单词边界。但是这个案子肯定会变得非常复杂和无限。
【解决方案2】:

不使用包并且只使用向量:

vec <- c('A, C, D', 
         'P, O, E', 
         'W, E, W', 
         'S, B, W')

ifelse(grepl('A', vec), 'A', ifelse(grepl('B', vec), 'B', NA))

您可以进一步简化它,但我将其保留为展开形式,以便您了解它的工作原理。

【讨论】:

    【解决方案3】:

    我们在下面提供绑带和基础解决方案。 strapply 解决方案很短,但是如果要匹配的元素可以是目标的子字符串,它就不起作用;但是,它们不是问题中的子字符串,因此它应该在那里工作。即使在这种情况下,基本解决方案也可以工作,因为它使用完全匹配而不是正则表达式。

    1) strapply (gsubfn) 在 gsubfn 中使用 strapply。如果您想要一个列表作为输出,请省略 simplify=TRUE。如果需要,[AB] 可以替换为 A|B

    library(gsubfn)
    
    strapply(x, "[AB]", empty = NA, simplify = TRUE)
    ## [1] "A" NA  NA  "B"
    

    2) base 拆分输入并为拆分的每个元素过滤掉匹配列表LL 可能足以满足您的需求,但如果不是,则最后一行将其简化为向量并用 NA 替换零长度元素。

    L <- lapply(strsplit(x, ", "), Filter, f = function(x) x %in% c("A", "B"))
    unlist(replace(L, !lengths(L), NA))
    ## [1] "A" NA  NA  "B"
    

    注意

    x <- c("A, C, D", "P, O, E", "W, E, W", "S, B, W")
    

    【讨论】:

      【解决方案4】:

      如果你想得到一个列表,你可以使用这个:

      library(magrittr)
      x = list(
           c("A", "C", "D"), 
           c("P", "O", "E"),
           c("W", "E", "W"),
           c("S", "B", "W")
           )
      
      myFunction <- function(x){
      
           x1 <- paste0(x, collapse = "")
      
           ifelse(stringr::str_detect(x1 , "A|B"), stringr::str_extract(x1, "A|B"), NA)
      }
      
      x %>% purrr::map(~ myFunction(.))
      

      【讨论】:

        【解决方案5】:

        在 Base R 中,您可以遍历字符串以检测并将它们分配给带有 [&lt;- ([&lt;-) 的输出。

        invec <- c(
          'A, C, D',
          'P, O, E',
          'W, E, W',
          'S, B, W')
        
        out <- rep(NA, length(invec))
        for(x in c('A', 'B')) out[grep(x, invec)] <- x
        out
        #[1] "A" NA  NA  "B"
        

        【讨论】:

          猜你喜欢
          • 2011-11-09
          • 2013-05-18
          • 2021-12-20
          • 2014-12-10
          • 1970-01-01
          • 1970-01-01
          • 2018-03-09
          • 2014-11-22
          • 2013-02-05
          相关资源
          最近更新 更多