基于正则表达式的n元语法提取

9
Karl Broman的文章:https://kbroman.wordpress.com/2015/06/22/randomized-hobbit-2/ 激发了我对正则表达式和ngrams的兴趣,只是出于好玩的心情。我尝试使用正则表达式来提取双字母组合。虽然知道有解析器可以完成这个工作,但我对正则表达式的逻辑很感兴趣(也就是说,这是一个自我挑战,但我失败了)。
下面给出一个最简示例和期望的输出结果。我的尝试中存在两个问题:
  1. 克隆(单词)被消耗掉了,不能在下一次使用。 如何使它们在第二次使用时可用? (例如,我希望在I like中已经使用过like后,like toast仍然可用)

  2. 我无法使单词之间的空格不被捕获(请注意我的输出中的尾随空格,即使我使用了(?:\\s*))。如何不捕获第n个(在这种情况下是第二个)单词的尾随空格? 我知道可以通过简单地使用:"(\\b[A-Za-z']+\\s)(\\b[A-Za-z']+)" 来完成2-gram,但我想将解决方案扩展到n-gram。 PS我知道\\w,但我不认为下划线和数字是单词部分,但认为'是单词部分。

MWE:

library(stringi)

x <- "I like toast and jam."

stringi::stri_extract_all_regex(
    x,
    pattern = "((\\b[A-Za-z']+\\b)(?:\\s*)){2}"
)

## [[1]]
## [1] "I like "    "toast and "

希望的输出:
## [[1]]
## [1] "I like"  "like toast"    "toast and"  "and jam"

也许解决问题#2的最佳方法是:"(\\b[A-Za-z']+\\s+){1}(\\b[A-Za-z']+)",通过将 1 调整为 n-1 来扩展正则表达式。 - Tyler Rinker
2个回答

8

以下是使用基本R正则表达式的一种方法。这可以轻松地扩展以处理任意n元组。技巧是将捕获组放置在一个正向预查断言内,例如(?=(my_overlapping_pattern))

x <- "I like toast and jam."
pattern <- "(?=(\\b[A-Za-z']+\\b \\b[A-Za-z']+\\b))"
matches<-gregexpr(pattern, x, perl=TRUE)
# a little post-processing needed to get the capture groups with regmatches
attr(matches[[1]], 'match.length') <- as.vector(attr(matches[[1]], 'capture.length')[,1])
regmatches(x, matches)

# [[1]]
# [1] "I like"     "like toast" "toast and"  "and jam"

我认为这对于未来的搜索者很有关联性:https://dev59.com/ml8e5IYBdhLWcg3wZpnw#25800334。我所缺少的相关术语是“重叠匹配”。感谢您的回复。 - Tyler Rinker

2

实际上,有一个应用程序可以做到这一点:即用于文本数据的定量分析的quanteda包。我的合著者Paul Nulty和我正在努力改进它,但它轻松处理您描述的使用情况。

install.packages("quanteda")
require(quanteda)
x <- "I like toast and jam."
> ngrams(x, 2)
## [[1]]
## [1] "i_like"     "like_toast" "toast_and"  "and_jam"   
ngrams(x, n = 2, concatenator = " ", toLower = FALSE)
## [[1]]
## [1] "I like"     "like toast" "toast and"  "and jam"   

不需要痛苦的正则表达式!

我认输,你对这个问题是正确的,但希望有人搜索关于单词n元组的问题时会发现这很有用! - Ken Benoit
1
谢谢,@Ken-Benoit,这看起来是一个有用的包,我期待着去尝试一下。 - Peter Verbeet
1
我今天在工作中使用了这个。软件包有很好的升级。+1 - Tyler Rinker
感谢 @Tyler Rinker。我希望很快有时间编写一些扩展,以便轻松地转换或使用 quanteda 对象与 qdap。我可以以 "tm-qdap" 速览作为基础开始。 - Ken Benoit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接