我有一个很大的文本正文,我想用有效的同义词替换单词(例如用同义词“car”替换所有出现的“cars”)。但我很难找到一个合适的(有效的方法)来做到这一点。
对于后面的分析,我使用text2vec
库,并希望将该库用于此任务(避免tm
减少依赖性)。
(低效)方式如下所示:
# setup data
text <- c("my automobile is quite nice", "I like my car")
syns <- list(
list(term = "happy_emotion", syns = c("nice", "like")),
list(term = "car", syns = c("automobile"))
)
我的蛮力解决方案是使用这样的东西并使用循环来查找单词并替换它们
library(stringr)
# works but is probably not the best...
text_res <- text
for (syn in syns) {
regex <- paste(syn$syns, collapse = "|")
text_res <- str_replace_all(text_res, pattern = regex, replacement = syn$term)
}
# which gives me what I want
text_res
# [1] "my car is quite happy_emotion" "I happy_emotion my car"
我过去常常使用tm
tm::content_transformer
(使用tm::tm_map
和tm
)来执行此操作,但我希望通过替换{来减少项目的依赖关系{1}} text2vec
更快。
我想最佳解决方案是以某种方式使用text2vec
s itoken
,但我不确定如何。有什么想法吗?
答案 0 :(得分:3)
很晚,但我仍想加2美分。 我看到2个解决方案
对str_replace_all
的小改进。由于它在内部进行矢量化,因此您可以在没有循环的情我认为会更快,但我没有制定任何基准。
regex_batch = sapply(syns, function(syn) paste(syn$syns, collapse = "|"))
names(regex_batch) = sapply(syns, function(x) x$term)
str_replace_all(text, regex_batch)
当然,此任务用于哈希表查找。据我所知,最快的实现是在fastmatch
包中。所以你可以编写自定义标记器,例如:
library(fastmatch)
syn_1 = c("nice", "like")
names(syn_1) = rep('happy_emotion', length(syn_1))
syn_2 = c("automobile")
names(syn_2) = rep('car', length(syn_2))
syn_replace_table = c(syn_1, syn_2)
custom_tokenizer = function(text) {
word_tokenizer(text) %>% lapply(function(x) {
i = fmatch(x, syn_replace_table)
ind = !is.na(i)
i = na.omit(i)
x[ind] = names(syn_replace_table)[i]
x
})
}
我敢打赌,第二种解决方案可以更快地运行,但需要制定一些基准测试。
答案 1 :(得分:2)
使用基础R这应该有效:
mgsub <- function(pattern,replacement,x) {
if (length(pattern) != length(replacement)){
stop("Pattern not equal to Replacment")
}
for (v in 1:length(pattern)) {
x <- gsub(pattern[v],replacement[v],x)
}
return(x )
}
mgsub(c("nice","like","automobile"),c(rep("happy_emotion",2),"car"),text)
答案 2 :(得分:1)
Dmitriy Selivanov解决方案的第一部分需要稍作改动。
library(stringr)
text <- c("my automobile is quite nice", "I like my car")
syns <- list(
list(term = "happy_emotion", syns = c("nice", "like")),
list(term = "car", syns = c("automobile"))
)
regex_batch <- sapply(syns, function(syn) syn$term)
names(regex_batch) <- sapply(syns, function(x) paste(x$syns, collapse = "|"))
text_res <- str_replace_all(text, regex_batch)
text_res
[1] "my car is quite happy_emotion" "I happy_emotion my car"