【问题标题】:Any way to require two matches instead of just one for TRUE with grepl?任何方式都需要两个匹配而不是一个匹配 TRUE 与 grepl?
【发布时间】:2016-03-31 03:33:16
【问题描述】:

我正在尝试使用 grepl 检测术语,但误报过多。我希望可能有一种方法可以要求列表中任何术语的两次成功匹配(我对我的一段数据进行手动编码,并试图让自动化至少大致对应于此,但我有大约 5 个是我手动编码的两倍)。我没有看到 grepl 接受任何需要多个匹配项才能触发 TRUE 的参数。有没有办法要求两个匹配来触发 TRUE 发现?还是我应该使用其他一些功能?

GenericColumn <- cbind(grepl(Genericpattern, Statement$Statement.Text, ignore.case = TRUE))

编辑:

这是一个更具体的例子:

Examplepattern <- 'apple|orange'
ExampleColumn <- cbind(grepl(Examplepattern, Rexample$Statement.Text, ignore.case = TRUE)) 

现在,所有这些都将通过 grepl 触发。我只希望有两个引用的项目触发 true。

示例数据:

Rexample <- structure(list(Statement.Text = structure(c(2L, 1L, 3L, 5L, 4L
), .Label = c("This apple is a test about an apple.", "This is a test about apples.", 
"This orange is a test about apples.", "This orange is a test about oranges.", 
"This orange is a test."), class = "factor")), .Names = "Statement.Text", row.names = c(NA, 
5L), class = "data.frame")

所需的输出:真、假、真、真、假

【问题讨论】:

  • 我不确定最好的具体示例是什么 - 实际代码中没有大量信息。我有一个模式:code Genericpattern
  • 请参阅how to write a great reproducible R example,以便我们为您提供帮助。确实,您可能应该使用 HTML 解析器进行解析,而不是正则表达式。 rvest::html_nodes 应该可以解决问题,搭配 CSS 或 XPath 选择器。
  • 我已经将数据保存在 csv 中,所以它已经从网站上移到了一个可操作的文件中——我现在只是想匹配术语两次而不是一次。我将按照该链接查看是否可以提出一个可重现的示例,尽管这与其说是错误问题,不如说是功能问题。
  • @alistaire 我在编辑的初始帖子中添加了一个具体示例(我认为)。

标签: regex r grepl


【解决方案1】:

你可以用花括号指定你想要在正则表达式中重复多少次,比如{2}(正好是它前面的两倍)、{2,5}(2-5 次)或{2,}(2 个或更多次)。但是,您需要允许您想要匹配的单词之间存在单词,因此您需要使用 * 量化的通配符 .(0 次或更多次)。

因此,如果您希望apple 或orange 匹配两次(包括apple 和orange,反之亦然),您可以使用

grepl('(apple.*|orange.*){2}', Rexample$Statement.Text, ignore.case = TRUE)
# [1] FALSE  TRUE  TRUE FALSE  TRUE

如果您希望apple 重复两次或orange 重复两次(但不是apple 一次和orange 一次),请分别量化:

grepl('(apple.*){2,}|(orange.*){2}', Rexample$Statement.Text, ignore.case = TRUE)
# [1] FALSE  TRUE FALSE FALSE  TRUE

【讨论】:

  • 不错的解决方案。看起来我们对期望的输出有不同的解释。请注意,您可以使用{2},因为即使“apple”出现超过 2 次,您仍然会得到TRUE。
  • 是的,实际上我已经安排它以匹配另一种方式并切换它。您对{2,} 和grepl 的看法是正确的;我猜grepl 的上限是没用的。
  • 有没有办法在其中放置一个 {2} 来覆盖整个列表?例如,如果任何一个术语出现两次对我来说并不重要,但如果总和只是两个呢?
  • @Matthew 请提供您想要的输出。也许 alistaire 可以使用这样的东西"(?:(?:apple|orange).*){2}" 第三个字符串应该返回 TRUE 还是 FALSE?
  • 更新了两者的选项,但 Jota 是对的,你应该在问题中指定你想要的输出。
【解决方案2】:

您可以尝试再次明确查找模式的正则表达式,例如 (?:apple|orange).*(?:apple|orange)

(pattern <- paste0("(?:", Examplepattern, ")", ".*", "(?:", Examplepattern, ")"))
#[1] "(?:apple|orange).*(?:apple|orange)"


grepl(pattern, Rexample$Statement.Text, ignore.case = TRUE, perl = TRUE)
#[1] FALSE  TRUE  TRUE FALSE  TRUE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2020-02-04
    • 1970-01-01
    相关资源
    最近更新 更多