【发布时间】:2014-11-30 18:33:00
【问题描述】:
我正在做一些 NLP 并试图从特定(有限)语料库中找到常见的 2-gram。我已经编写了一个 for 循环来执行我想要的操作,但是在任何实际数据量上运行都需要很长时间。我觉得我应该可以通过 apply 来做到这一点,但我一生都无法弄清楚如何去做。非常感谢任何帮助。
我已将语料库标记化并 ngram 化为以下数据帧(这显然只是一个小子集,例如)。
tk
word Freq
5477 with 186
1998 for 182
2644 it 179
3482 on 174
5354 was 168
ng
ngrams Freq w1 w2 rate
2434 at the 30 at the 0
16027 with the 29 with the 0
140 <> But 28 <> But 0
223 <> He 28 <> He 0
6885 I have 28 I have 0
我有以下适用于这两个数据帧的 for 循环:
for(i in 1:dim(ng)[1]) {
tkw1 <- ifelse(length(tk$Freq[tk$word==ng$w1[i]]) > 0,
tk$Freq[tk$word==ng$w1[i]], 0)
tkw2 <- ifelse(length(tk$Freq[tk$word==ng$w2[i]]) > 0,
tk$Freq[tk$word==ng$w2[i]], 0)
dnm <- tkw1 + tkw2
dnm <- ifelse(dnm >= 1, dnm, ng$Freq[i])
ng$rate[i] <- ng$Freq[i] / dnm
}
这个想法是为每一行计算一个“比率”,它基本上是 2-gram 出现的次数除以每个单词单独出现的次数(总和)。 for 循环可以做到这一点,但在大规模使用时速度很慢。
旁注:有一些 ifelse 语句对于调试有时(由于不完善的预处理)2-gram 中的一个单词与 tk 数据帧中的单词不匹配的事实是必要的。
Sooo,有没有办法通过 apply(或者可能是 sapply 或 tapply)来做到这一点?我已经为此工作了好几个小时,但我无法弄清楚。 谢谢!
如果这有帮助,我最近的尝试是:
TGrate <- function(ng, w1, w2, Freq){
tkw1 <- ifelse(length(tk$Freq[tk$word==w1]) > 0,
tk$Freq[tk$word==w1], 0)
tkw2 <- ifelse(length(tk$Freq[tk$word==w2]) > 0,
tk$Freq[tk$word==w2], 0)
dnm <- tkw1 + tkw2
dnm <- ifelse(dnm >= 1, dnm, Freq)
rate <- as.numeric(Freq) / as.numeric(dnm)
rate
}
ng$rate <- apply(ng, 1, TGrate, w1="w1", w2="w2", Freq="Freq")
但这只会产生一堆 NA。
【问题讨论】: