处理百万级区间时如何加速dplyr::between的执行?
高效统计区间内异常值数量
你有一个包含起始列X1和结束列X2的数据框,还有一个异常值列表,需要统计每个区间内落入的异常值数量。原代码用for循环实现,但面对百万行数据时效率极低,以下是几种优化方案:
原代码回顾
library("dplyr") set.seed(2022) dat = data.frame(matrix(sort(sample(1:500, 50)), ncol = 2, byrow = T)) colnames(dat) <- c("X1", "X2") dat$Outliers = NA outliers = sort(sample(1:500, 30)) for (i in 1:25){ dat$Outliers[i] = length(which(between(outliers, dat$X1[i], dat$X2[i]) == T)) }
优化方案1:基础R二分查找(最快)
因为outliers已排序,用findInterval快速定位区间上下限在异常值中的位置,位置差即为区间内异常值数量,完全向量化操作,无循环:
# 若真实数据中outliers未排序,先执行 outliers <- sort(outliers) lower_pos <- findInterval(dat$X1, outliers, rightmost.closed = TRUE) upper_pos <- findInterval(dat$X2, outliers, rightmost.closed = TRUE) dat$Outliers <- upper_pos - lower_pos
优化方案2:data.table非等值连接
data.table的非等值连接在百万级数据集上效率优异,适合复杂数据场景:
library(data.table) # 转换为data.table格式 setDT(dat) outliers_dt <- data.table(val = outliers) # 非等值连接并按区间计数 dat[, Outliers := outliers_dt[.SD, on = .(val >= X1, val <= X2), .N, by = .EACHI]$N]
优化方案3:dplyr+向量化操作
若偏好dplyr语法,用purrr::map2配合向量化判断,效率远高于for循环:
library(dplyr) library(purrr) dat <- dat %>% mutate(Outliers = map2_dbl(X1, X2, ~sum(between(outliers, .x, .y))))
方案对比
- 基础R二分查找:速度最快、内存占用最低,优先推荐
- data.table非等值连接:大数据集下表现稳定,适配复杂数据逻辑
- dplyr+map2:语法简洁,但百万行数据下效率略逊于前两者
内容的提问来源于stack exchange,提问作者Math Avengers
相关产品推荐
相关产品推荐

