大样本下跨时间计算企业与准入银行平均哈弗辛距离方案咨询
R 大规模企业-银行距离批量计算高效实现方案
核心优化逻辑
- 避免嵌套循环运算,将经纬度转弧度、准入银行分组等重复计算步骤提前做预处理,减少无效运算
- 采用向量化运算替代显式循环,利用R底层C实现提速,运算效率至少提升1~2个数量级
- 减少不必要的条件判断,提前按准入时间聚合银行列表,计算时直接调用对应时间的银行坐标数组即可
预处理步骤
首先转换字段类型,预计算所有坐标的弧度值、按准入时间分组的银行列表:
library(data.table) # 转为data.table提速 setDT(Data_firm) setDT(Data_bank) # 字段类型转换,经纬度提前转弧度(哈弗辛公式前置要求,避免重复计算) Data_firm[, `:=`( time = as.integer(time), lon_firm_rad = as.numeric(Longfirm) * pi / 180, lat_firm_rad = as.numeric(Latfirm) * pi / 180 )] Data_bank[, `:=`( first_entry = as.integer(first_entry), lon_bank_rad = as.numeric(Longbank) * pi / 180, lat_bank_rad = as.numeric(Latbank) * pi / 180 )] # 预生成每个时间点对应的已准入银行坐标列表 max_t <- max(Data_firm$time) bank_list_by_t <- lapply(1:max_t, function(t) { Data_bank[first_entry <= t, .(lon_bank_rad, lat_bank_rad)] }) names(bank_list_by_t) <- as.character(1:max_t)
向量化哈弗辛平均距离计算函数
haversine_avg <- function(lon1, lat1, bank_coords) { lon2 <- bank_coords$lon_bank_rad lat2 <- bank_coords$lat_bank_rad # 向量化计算该企业和所有准入银行的距离 dlon <- lon2 - lon1 dlat <- lat2 - lat1 a <- sin(dlat/2)^2 + cos(lat1) * cos(lat2) * sin(dlon/2)^2 c <- 2 * atan2(sqrt(a), sqrt(1-a)) # 地球平均半径取6371km,返回平均距离 return(mean(6371 * c)) }
批量计算结果
# 逐行遍历企业记录,计算对应平均距离 Data_firm[, avg_dist := haversine_avg(lon_firm_rad, lat_firm_rad, bank_list_by_t[[as.character(time)]]), by = 1:nrow(Data_firm)]
额外提速方案
- 若存在大量同一城市的企业,可提前对企业经纬度+时间去重,相同组合仅计算一次平均距离再匹配回原表,可大幅减少重复运算
- 追求极致性能可将哈弗辛计算逻辑用Rcpp改写,整体运算速度还能再提升3~5倍,30万条记录预计耗时在10秒以内
- 若业务允许过滤超远距离银行,可提前用sf包构建银行空间索引,通过空间范围过滤后再计算距离,运算量会进一步降低
内容的提问来源于stack exchange,提问作者Nicolas
相关产品推荐
相关产品推荐

