使用tm包,我有一个包含10,900个文档的语料库( docs )。
docs = Corpus(VectorSource(abstracts$abstract))
我还有一个术语列表( termslist )及其所有同义词和不同的拼写。我用它将每个同义词或拼写转换成一个术语。
Term, Synonyms
term1, synonym1
term1, synonym2
term1, synonym3
term2, synonym1
... etc
我现在正在这样做的方法是循环遍历所有文档,另一个nester遍历所有术语以查找和替换。
for (s in 1:length(docs)){
for (i in 1:nrow(termslist)){
docs[[s]]$content<-gsub(termslist[i,2], termslist[i,1], docs[[s]])
}
print(s)
}
目前这需要一秒钟的文件(在 termslist 中有大约1000行),这意味着10,900秒,大约是6小时!
是否有更优化的方式在tm包内或R内执行此操作?
更新:
math.coffee的回答实际上很有帮助。我不得不重新创建一个具有唯一术语作为行的表,第二列将是由'|'分隔的同义词,然后只是循环它们。现在它的时间比以前少得多。** [乱码]创建新表的代码:
newtermslist<-list()
authname<-unique(termslist[,1])
newtermslist<- cbind(newtermslist,authname)
syns<-list()
for (i in seq(authname)){
syns<- rbind(syns,
paste0('(',
paste(termslist[which(termslist[,1]==authname[i]),2],collapse='|')
, ')')
)
}
newtermslist<-cbind(newtermslist,syns)
newtermslist<-cbind(unlist(newtermslist[,1]),unlist(newtermslist[,2]))
答案 0 :(得分:1)
我认为当您希望执行多次替换时,这可能是唯一的方法(即按顺序,将替换的输出保存为下次替换的输入)。
但是,你可能会尝试一些速度(你必须做一些基准测试来比较):
fixed=T
(因为您的同义词不是正则表达式而是字面拼写),useBytes=T
(**请参阅?gsub
- 如果您有多字节区域设置,这可能是也可能不是一个好主意)。或blue
包含同义词cerulean
,cobalt
和sky
,则您的正则表达式可能为(cerulean|cobalt|sky)
,并且替换blue
,以便blue
的所有同义词在一次迭代中被替换而不是在3次单独的迭代中被替换。为此,您需要预先处理您的条款清单 - 例如newtermslist <- ddply(terms, .(term), summarize, regex=paste0('(', paste(synonym, collapse='|'), ')'))
然后对此进行当前循环。您将拥有fixed=F
(默认值,即使用正则表达式)。?tm_map
和?content_transformer
。我不确定这些是否会加速,但你可以试试。(重新基准测试 - 尝试使用library(rbenchmark); benchmark(expression1, expression2, ...)
,或者使用{ol}&{39;} system.time
作为时间安排,Rprof
进行性能分析
答案 1 :(得分:1)
在我通过并行解决方案并行处理之后,我回答了我自己的问题。它应该更快地运行代码,但我还没有比较这两个解决方案。
library(doParallel)
library(foreach)
cl<-makeCluster(detectCores())
registerDoParallel(cl)
system.time({ # this one to print how long it takes after it evaluate the expression
foreach(s=1:length(docs)) %:% foreach(i=1:nrow(newtermslist)) %dopar% {
docs[[s]]$content<-gsub(newtermslist[i,2], newtermslist[i,1], docs[[s]]$content)
}
})
stopCluster(cl)