【问题标题】:Construct a character vector of multi-word phrases using regex for building dfm using quanteda in R使用正则表达式构建多词短语的字符向量,以使用 R 中的 quanteda 构建 dfm
【发布时间】:2018-05-22 01:04:13
【问题描述】:

我已经非常满意 quanteda 的 textstat_collocation() 用于提取 MWE。现在我正在尝试提取与特定模式匹配的所有匹配项,而不管它们的频率如何。

我的目标是通过从使用正则表达式模式构建的 dfm() 中提取专长名称来创建字符向量。然后,我将在“select”参数中使用此字符向量来构建 dfm。我可能还想使用这个字符向量添加到字典中,用作在管道后期构建 dfms 的本体。

模式是:“aged xx-xx”,其中 x 是一个数字。

我使用了正则表达式模式 "aged\s([0-9]{2}-[0-9]{2})" here 并获得了所需的匹配项。但是当我在 R 中尝试时(在“\s”之前添加一个额外的“\”),我没有得到任何匹配。

当我这样做时:

txt <- c("In India, male smokers aged 20-45 perceive brandX positively.",
              "In Spain, female buyers aged 30-39 don't purchase brandY.")
ageGroups <- dfm(txt, select = "aged\\s([0-9]{2}-[0-9]{2})", valuetype = "regex")
featnames(ageGroups)

我明白了:

character(0)

但是,当我尝试时:

ageGroups <- dfm(txt, select = "([0-9]{2}-[0-9]{2})", valuetype = "regex")
featnames(ageGroups)

我明白了:

[1] "20-45" "30-39"

似乎我无法捕获正则表达式中的空白。我在 SO 中遇到了许多类似的问题,也许 this 是最相关的,但仍然无法实现我的具体目标。

我也试过了:

tokens <- tokens(txt, remove_punct = FALSE, remove_numbers = FALSE, remove_symbols = FALSE)
tokensCompunded <- tokens_compound(tokens, pattern =  "aged\\s([0-9]{2}-[0-9]{2})", valuetype = "regex")
attr(tokensCompunded, "types")

但我拿回了所有代币:

[1] "In"         " "          "India"      ","          "male"       "smokers"    "aged"       "20-45"      "perceive"  
[10] "brandX"     "positively" "."          "Spain"      "female"     "buyers"     "30-39"      "don't"      "purchase"  
[19] "brandY" 

我认为可能还有其他几种更有效的方法可以使用带有 quanteda 的正则表达式(或 glob)来提取字符向量,我很高兴学习如何使用这个令人惊叹的 R 包的新方法。

感谢您的帮助!

修改原始问题:

ThisSO 中的其他问题也有类似的要求,即使用 kwic 对象检测多词短语,并且可以通过以下添加进一步扩展以实现上述目标: p>

kwicObject <- kwic(corpus, pattern = phrase("aged ([0-9]{2}-[0-9]{2})"), valuetype = "regex")
unique(kwicObject$keyword)

【问题讨论】:

  • 感谢维克托!当我使用 'pattern = phrase("aged\\s+([0-9]{2}-[0-9]{2})")' 创建 kwic 对象时,我得到 "kwic object with 0 rows" .我还尝试使用 tokens_select() 和 tokens_compound() 并在 attr(x, "type") 时得到 "character(0)"。但是,Ken 的“年龄 [0-9]{2}-[0-9]{2}”对于创建具有多词短语的 kwic 对象也确实有效。
  • 我认为这个问题应该重新打开,因为它不是一个 exact 副本。关闭可能与关闭者的其他答案竞争的问题似乎也有点不礼貌。

标签: r regex quanteda


【解决方案1】:

这里的问题是目标文本和多词pattern(包含空格)的标记方式不同。在您的示例中,您为多个标记(包括空格分隔符)应用了正则表达式,但搜索目标已被拆分为单个标记。

我们为此设计了一个解决方案,一个名为phrase() 的函数。来自?pattern

空白没有特权,因此在字符向量中,白色 空间是按字面意思解释的。如果你想考虑 以空格分隔的元素作为标记序列,将 phrase() 中的参数。

所以在这种情况下:

pat <- "aged [0-9]{2}-[0-9]{2}"

toks2 <- tokens_select(toks, pattern = phrase(pat), valuetype = "regex")
toks2
# tokens from 2 documents.
# text1 :
# [1] "aged"  "20-45"
# 
# text2 :
# [1] "aged"  "30-39"

在这里,我们看到选择有效,因为 phrase() 包装器将模式转换为匹配序列。

如果您想让这些成为单个令牌,您可以将相同的 pattern 参数发送到 tokens_compound()

toks3 <- tokens_compound(toks2, pattern = phrase(pat), 
                         valuetype = "regex", concatenator = " ")
toks3
# tokens from 2 documents.
# text1 :
# [1] "aged 20-45"
# 
# text2 :
# [1] "aged 30-39"

最后,您可以使用它来构建一个 dfm,其中每个多词匹配都是一个特征。除非您首先在标记阶段执行连接,否则这将无法工作,因为根据定义,dfm 在其特征中没有顺序。

dfm(toks3)
# Document-feature matrix of: 2 documents, 2 features (50% sparse).
# 2 x 2 sparse Matrix of class "dfm"
#        features
# docs    aged 20-45 aged 30-39
#   text1          1          0
#   text2          0          1

【讨论】:

  • 这种方法完美地解决了我的要求。谢谢肯。
【解决方案2】:

您可以更改正则表达式模式:

select = "aged.*([0-9]{2}-[0-9]{2})"

【讨论】:

  • 请解释一下这个正则表达式如何解决 OP 问题。
  • 欢迎来到 StackOverflow!尽管此答案可能是正确且有用的,但如果您随附一些解释以解释它如何帮助解决问题,则最好。如果有更改(可能不相关)导致它停止工作并且用户需要了解它曾经是如何工作的,这在未来变得特别有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多