【问题标题】:R's grepl() to find multiple strings exists [duplicate]R用于查找多个字符串的grepl()存在[重复]
【发布时间】:2017-05-24 08:26:51
【问题描述】:
grepl("instance|percentage", labelTest$Text)

如果存在instancepercentage 中的任何一个,将返回true。

只有当这两个术语都存在时,我如何才能实现?

【问题讨论】:

  • grep 用“实例”一次然后用“百分比”做同样的事情怎么样?获取回复(如 T 或 F)并将它们组合起来?
  • 我需要用这个组合填充一个excel,下面是代码:labelTest$label[ grep("instance", labelTest$Text)] <- "combination1" 所以一个带有“instance”而另一个带有“percentage”将不起作用。
  • labelTest$label[ grep("instance", labelTest$Text) & grep("percentage", labelTest$Text)] <- "combination1" 是 @agerom 的建议,应该可以工作
  • 以上一个不起作用它的行为是 |操作员,并给出以下警告:longer object length is not a multiple of shorter object length

标签: r grepl


【解决方案1】:
Text <- c("instance", "percentage", "n", 
          "instance percentage", "percentage instance")

grepl("instance|percentage", Text)
# TRUE  TRUE FALSE  TRUE  TRUE

grepl("instance.*percentage|percentage.*instance", Text)
# FALSE FALSE FALSE TRUE  TRUE

后一种通过寻找:

('instance')(any character sequence)('percentage')  
OR  
('percentage')(any character sequence)('instance')

当然,如果您需要找到两个以上单词的任意组合,这将变得相当复杂。那么 cmets 中提到的解决方案会更容易实现和阅读。

匹配多个单词时可能相关的另一种替代方法是使用正向预测(可以被认为是“非消耗”匹配)。为此,您必须激活 perl 正则表达式。

# create a vector of word combinations
set.seed(1)
words <- c("instance", "percentage", "element",
           "character", "n", "o", "p")
Text2 <- replicate(10, paste(sample(words, 5), collapse=" "))

# grepl with multiple positive look-ahead
longperl <- grepl("(?=.*instance)(?=.*percentage)(?=.*element)(?=.*character)",
  Text2, perl=TRUE)

# this is equivalent to the solution proposed in the comments
longstrd <- grepl("instance", Text2) & 
          grepl("percentage", Text2) & 
             grepl("element", Text2) & 
           grepl("character", Text2)

# they produce identical results
identical(longperl, longstrd)

此外,如果您将模式存储在向量中,则可以显着压缩表达式,从而为您提供

pat <- c("instance", "percentage", "element", "character")

longperl <- grepl(paste0("(?=.*", pat, ")", collapse=""), Text2, perl=TRUE)
longstrd <- rowSums(sapply(pat, grepl, Text2) - 1L) == 0L

如 cmets 中所要求的,如果您想匹配确切的单词,即不匹配子字符串,我们可以使用 \\b 指定单词边界。例如:

tx <- c("cent element", "percentage element", "element cent", "element centimetre")

grepl("(?=.*\\bcent\\b)(?=.*element)", tx, perl=TRUE)
# TRUE FALSE  TRUE FALSE
grepl("element", tx) & grepl("\\bcent\\b", tx)
# TRUE FALSE  TRUE FALSE

【讨论】:

  • 不确定这是否适用于整个单词。例如,用"table" 替换"instance" 似乎也能捕捉到"marketable" 这样的情况。我尝试添加"\\stable" 以在"table" 之前包含一个空格,但这也不起作用。有什么建议吗?
  • @val:如果您使用\\b 来指示单词边界,它应该可以工作。
【解决方案2】:

如果这两个术语都出现在向量“labelTest$Text”的一个项目中,那么您将只得到“TRUE”。 我认为这是问题的确切答案,并且比其他解决方案要短得多。

grepl("instance",labelTest$Text) & grepl("percentage",labelTest$Text)

【讨论】:

  • 请澄清你的答案
  • 请澄清您的困惑
  • 不鼓励仅使用代码的答案,请下次添加一些上下文来解释此答案将如何解决相关问题。
【解决方案3】:

使用intersect 并为每个单词输入grep

library(data.table) #used for subsetting text vector below

vector_of_text[
  intersect(
    grep(vector_of_text , pattern = "pattern1"),
    grep(vector_of_text , pattern = "pattern2")
  )
]

【讨论】:

  • 我在这里没有看到 data.table 的使用。你能澄清一下吗?另外,我认为您想要:vector_of_text [ grep(vector_of_text , pattern = "pattern1") & grep(vector_of_text , pattern = "pattern2") ]。没有使用 intersect() 和 &,但我们仍然有一个潜在的问题,即命中将包含包含搜索词的字符串(如“instance1”代表“instance”)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多