【问题标题】:Speed up the lookup procedure加快查找过程
【发布时间】:2017-02-27 10:59:08
【问题描述】:

我有两张桌子:coc_dataDTcoc_data 表包含单词对之间的共现频率。它的结构类似于:

   word1 word2 freq
1      A     B    1
2      A     C    2
3      A     D    3
4      A     E    2

第二个表,DT 包含每个单词在不同年份的频率,例如:

   word year weight
1     A 1966      9
2     A 1967      3
3     A 1968      1
4     A 1969      4
5     A 1970     10
6     B 1966      9

实际上,coc_data 目前有 150.000 行,DT 有大约 450.000 行。下面是 R 代码,它模拟了两个数据集。

# Prerequisites
library(data.table)
set.seed(123)
n <- 5

# Simulate co-occurrence data [coc_data]
words <- LETTERS[1:n]
# Times each word used
freq <- sample(10, n, replace = TRUE)
# Co-occurrence data.frame
coc_data <- setNames(data.frame(t(combn(words,2))),c("word1", "word2"))
coc_data$freq <- apply(combn(freq, 2), 2, function(x) sample(1:min(x), 1))

# Simulate frequency table [DT]
years <- (1965 + 1):(1965 + 5)
word <- sort(rep(LETTERS[1:n], 5))
year <- rep(years, 5)
weight <- sample(10, 25, replace = TRUE)
freq_data <- data.frame(word = word, year = year, weight = weight)
# Combine to data.table for speed
DT <- data.table(freq_data, key = c("word", "year"))

我的任务是使用以下函数根据DT 表中的频率对coc_data 表中的频率进行归一化:

my_fun <- function(x, freq_data, years) {
  word1 <- x[1]
  word2 <- x[2]
  freq12 <- as.numeric(x[3])
  freq1 <- sum(DT[word == word1 & year %in% years]$weight)
  freq2 <- sum(DT[word == word2 & year %in% years]$weight)
  ei <- (freq12^2) / (freq1 * freq2)
  return(ei)
}

然后我使用apply() 函数将my_fun 函数应用于coc_data 表的每一行:

apply(X = coc_data, MARGIN = 1, FUN = my_fun, freq_data = DT, years = years)

因为DT 查找表很大,整个映射过程需要很长时间。我想知道如何改进我的代码以加快计算速度。

【问题讨论】:

  • 我认为它不会有太大改进,但如果你想使用 data.table 功能,你可以将freq1 &lt;- sum(DT[word == word1 &amp; year %in% years]$weight) 更改为freq1 &lt;- DT[word == word1 &amp; year %in% years, weight, sum](我没有测试它,我也没有使用 data.table 很多,所以检查它是否以等效的方式工作)

标签: r performance optimization


【解决方案1】:

由于my_fun 中的years 参数对于使用apply 的实际用法是恒定的,因此您可以先计算所有单词的频率:

f<-aggregate(weight~word,data=DT,FUN=sum)

现在将其转换为哈希,例如:

hs<-f$weight
names(hs)<-f$word

现在在my_fun 中通过查找 hs[word] 使用预先计算的频率。这应该更快。

更好 - 您正在寻找的答案是

(coc_data$freq)^2 / (hs[coc_data$word1] * hs[coc_data$word2])

data.table 的实现是:

f <- DT[, sum(weight), word]
vec <- setNames(f$V1, f$word)

setDT(coc_data)[, freq_new := freq^2 / (vec[word1] * vec[word2])]

给出以下结果:

> coc_data
    word1 word2 freq     freq_new
 1:     A     B    1 0.0014792899
 2:     A     C    1 0.0016025641
 3:     A     D    1 0.0010683761
 4:     A     E    1 0.0013262599
 5:     B     C    5 0.0434027778
 6:     B     D    1 0.0011574074
 7:     B     E    1 0.0014367816
 8:     C     D    4 0.0123456790
 9:     C     E    1 0.0009578544
10:     D     E    2 0.0047562426

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-11
    • 2023-01-25
    相关资源
    最近更新 更多