使用正则表达式构造多词短语的字符向量,用于在R中使用quanteda构建dfm

时间:2018-05-20 13:05:00

标签: r regex quanteda

我曾经非常满意quanteda的textstat_collocation()来提取MWE。现在我试图提取所有匹配特定模式的匹配,而不管它们的频率如何。

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

模式是:“老化的xx-xx”,其中x是数字。

我使用正则表达式模式“age \ s([0-9] {2} - [0-9] {2})”change the format of your data并获得所需的匹配。但是当我在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中经历了许多类似的问题,或许here是最相关的,但仍然无法使我的具体目标发挥作用。

我也尝试过:

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包的新方法。

感谢您的帮助!

修改为原始问题:

在SO中的

this其他问题也有类似的要求,即使用kwic对象检测多词短语,并且可以进一步扩展以实现上述目标,并增加以下内容:

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

2 个答案:

答案 0 :(得分:0)

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

<img>

答案 1 :(得分:0)

这里的问题是目标文本和多字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