问题描述
我正在验证一些数据,我注意到当我使用 grepl 搜索使用 sum(grepl('time',x = df$Comments))
的术语时(其中 df 是一个简单的 data.frame,其中每行包含不同的推文),我尝试比较它到 textstat_frequency
在 quanteda 包中使用
df %>% corpus(text_field='Comments') %>% dfm(tolower = T,remove = stop_words,remove_punct = T,remove_symbols = T,remove_numbers = T) %>% textstat_frequency()
我得到两个不同的结果
使用 grepl,我得到 2718,使用 quanteda 我得到:
feature frequency rank docfreq group
time 2879 1 2113 all
textstat_frequency 不是解决这个问题的方法吗?
解决方法
可能有两个原因。
-
grepl()
仅在文档(或TRUE
向量的字符元素)中出现一次匹配时才计算Comments
。textstat_frequency()
对每次出现的令牌进行计数。这可能是后者计数比前者更多的原因之一。 -
您的文本字段中出现了大写的“时间”,这与您使用
grepl()
的方式不匹配,而默认情况下,dfm()
具有tolower = TRUE
作为默认值。因此textstat_frequency()
会计算大写出现的次数,而您对grepl()
的使用则不会。但是,您可以使用grepl(...,ignore.case = TRUE)
更改此设置。
示例:
txt <- c("This time is new.","Time,time,time.","Time is on our side.")
sum(grepl("time",txt))
## [1] 2
sum(grepl("time",txt,ignore.case = TRUE))
## [1] 3
library("quanteda")
## Package version: 2.1.2
dfm(txt) %>%
textstat_frequency(n = 1)
## feature frequency rank docfreq group
## 1 time 5 1 3 all
如果您想通过正则表达式类型的解决方案匹配计数行为,您可以通过以下方式使其工作:
stringi::stri_extract_all_fixed(txt,"time",case_insensitive = TRUE) %>%
unlist() %>%
length()
## [1] 5
但这仍然会有不考虑单词边界的缺点,因此仍将“某个时间”计为“时间”。另一方面,标记化和使用 textstat_frequency()
将考虑单词边界,因为它已对文本进行标记化,包括连接到标点字符(如 time,
或 "time"
)的单词。
所以 textstat_frequency()
绝对是解决这个问题的方法。