[英]R Alternatives to a for loop for searching through a large dataset
这里的目标是识别和计数 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)
我将这些数据合并到 dataframe 中以模拟我的实际数据集,将它们转换为数字并编写以下 function 以获得我想要的 output。(注意:列 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
)
A | 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 很陌生,一个常见的建议是使用矢量化来提高效率。 但是,在查看 .net 上提供的示例时,我不知道在这种情况下是否可行。
很乐意听到任何建议,并随时指出错误。 谢谢!
为什么向量a
和b
字符? 它们应该是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
colSums
+ outer
怎么样?
transform(
type.convert(data.frame(a, b), as.is = TRUE),
C = colSums(abs(outer(a, b, `-`)) <= 1)
)
a 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
由于您的数据非常大, outer
和lapply
方法将非常慢(对于outer
您需要 14901.2 Gb 的 RAM)。 我建议使用data.table
require(data.table)
dt <- as.data.table(df)
dt[, id := 1:.N] # add id as maybe you have duplicated values
setkey(dt, id)
dt[, b1 := b - 1L]
dt[, b2 := b + 1L]
x <- dt[dt, on = .(a >= b1, a <= b2)] # non-equi join
x <- x[, .(c = sum(!is.na(b1))), keyby = .(id = i.id)]
dt[x, c := i.c, on = 'id']
dt
# a b id b1 b2 c
# 1: 1231210 1 1 0 2 0
# 2: 1231211 2 2 1 3 0
# 3: 1231212 3 3 2 4 0
# 4: 98798 4 4 3 5 0
# 5: 98797 5 5 4 6 0
# 6: 98796 6 6 5 7 0
# 7: 555125 1231209 7 1231208 1231210 1
# 8: 555127 98797 8 98796 98798 3
# 9: 555128 555126 9 555125 555127 2
dt[, id := NULL][, b1 := NULL][, b2 := NULL] # remove colls
ps 检查a
和b
之前是否转换为整数...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.