首页 > 解决方案 > R 用于搜索大型数据集的 for 循环的替代方案

问题描述

这里的目标是识别和计算 b 列中的条目是否与 a 列中的条目匹配,范围为 +/-1(或根据需要)。提供了一个简化版本:

a <- c("1231210","1231211", "1231212", "98798", "98797", "98796", "555125", "555127","555128")
b <- c("1", "2", "3", "4", "5", "6", "1231209", "98797", "555126")
df <- data.frame(a, b)

我将这些数据合并到一个数据框中以模拟我的实际数据集,将它们转换为数字并编写以下函数来获得我想要的输出。(注意:列 a 不必是 df 的一部分,但我想可以是一个单独的列表?)

df$c <- mapply(
function(x){
    count = 0
    for (i in df$a){
        if (abs(i-x) <= 1){
            count = count +1
        }
    }
    paste0(count)
},
df$b
)
一种 b C
1 1231210 1 0
2 1231211 2 0
3 1231212 3 0
4 98798 4 0
5 98797 5 0
6 98796 6 0
7 555125 1231209 1
8 555127 98797 3
9 555128 555126 2

虽然这对于试验数据集似乎工作正常,但我的实际数据集有超过200 万行,这意味着 2M^2 次迭代?(3 小时后仍在运行)我想知道是否有替代策略来解决这个问题,最好只使用基本 R 函数。

我对 R 很陌生,一个常见的建议是使用矢量化来提高效率。但是,在查看网上提供的示例时,我不知道在这种情况下是否可行。

很想听听任何建议,并随时指出错误。谢谢!

标签: rdataframeperformancefor-loop

解决方案


为什么是向量ab字符?他们应该是numeric

a <- c(1231210,1231211, 1231212, 98798, 98797, 98796, 555125, 555127,555128)
b <- c(1, 2, 3, 4, 5, 6, 1231209, 98797, 555126)

您可以通过仅使用一个循环和矢量化来简化:

unlist(lapply(b, function(x) sum(abs(a-x) <= limit)))

其中limit是描述允许差异的变量。为limit <- 1您获得:

 [1] 0 0 0 0 0 0 1 3 2

推荐阅读