【发布时间】:2016-12-08 22:24:43
【问题描述】:
我一直在进行一些文本抓取/分析。我做的一件事是从文档中提取最热门的单词来比较和了解不同的指标。这是快速和容易的。但是,定义要使用的分隔符并提取单个单词而不是短语会从分析中删除信息,这成为了一个问题。例如 .Net Developer 转换后成为 net 和 developer。我已经有一个其他人放弃的旧项目中的固定短语/单词列表。下一步是从多个文档的多行中提取特定关键字。
我一直在研究几种技术,包括矢量化、并行处理、在 R 中使用 C++ 代码等。展望未来,我将尝试所有这些技术,并尝试加快我的流程,并为我未来的项目提供这些工具。同时(没有实验)我想知道哪些调整是显而易见的,这将显着减少所花费的时间,例如将部分代码移到循环外,使用更好的包等 我也有一个进度条,但如果它显着减慢了我的循环,我可以将其删除。
这是我的代码:
words <- read.csv("keyphrases.csv")
df <- data.frame(x=(list.files("sec/new/")))
total = length(df$x)
pb <- txtProgressBar(title = "Progress Bar", min = 0, max =total , width = 300, style=3)
for (i in df$x){
s <- read.csv(paste0("sec/new/",i))
u <- do.call(rbind, pblapply(words$words, function(x){
t <- data.frame(ref= s[,2], words = stri_extract(s[,3], coll=x))
t<-na.omit(t)
}))
write.csv(u,paste0("sec/new_results/new/",i), row.names = F)
setTxtProgressBar(pb, i, title=paste( round(which(df$x== i)/total*100, 2),"% done"))
}
所以words 有 60,000 行单词/短语 - 每行不超过 30 个字符。长度 i 约为 4000,其中每个 i 有 100 到 5000 行,每行有 1 到 5000 个字符。如果我的问题需要重现,可以使用任何随机字符/字符串。
我只使用 lapply 是因为将它与 rbind 和 do.call 结合使用效果非常好,循环中的循环也可能会显着减慢进程。
所以我可以立即做一些事情,对吗?将 data.frame 交换为 data.table 或使用向量。以某种方式在循环外进行读写?也许写成这样一个循环不是嵌套的?
提前致谢
编辑
需要加速的关键元素是提取。我是使用上面的 lapply 还是将其缩减为:
for(x in words$words){t<-data.table(words=stri_extract(s[,3], coll=x))}
这仍然需要很长时间。在这种情况下,技能和 t 是数据表。
EDIT2
尝试创建可重现的数据:
set.seed(42)
words <- data.frame(words=rnorm(1:60000))
words$wwords <- as.String(words$words)
set.seed(42)
file1 <- data.frame(x=rnorm(1:5000))
file1$x<-as.String(file1$x)
pblapply(words$words, function(x){
t <- data.frame(words = stri_extract(file1$x, coll=x))
})
【问题讨论】:
-
如果你真的提供一些玩具数据来执行你的代码会很有帮助,请参阅stackoverflow.com/questions/5963269/…
-
我无法提供我的数据,我将文件的大小放在我的问题中,能回答这个问题的人在创建随机字符串/文件方面会比我好得多。也许它就像制作数字的随机向量一样简单,我以前没有尝试过。
-
我说的是准备玩具数据。经验表明,如果人们可以先运行您的代码,他们更有可能直接提出问题 - 而无需自己模拟数据。
-
在第二次编辑中尝试过此操作。虽然不知道如何给人们文件夹/文件。只是一个读取一个文件的基本示例。
-
@OliPaul 例如通过
rnorm等函数生成数据时请使用set.seed。
标签: r performance loops optimization