如何将循环转换为apply族函数以提升效率?(经纬度距离计算场景)
嘿,我来帮你搞定这个效率问题!
首先得说,你的for循环慢是因为R里逐行循环的开销特别大,尤其是数据量上去之后,几小时的等待太折磨人了。其实向量化操作才是R处理大数据的正确打开方式,比apply族还要高效,而且代码更简洁。
最优方案:直接用向量化的distm计算
distm函数本身就支持批量处理多个坐标点,不用逐行循环!你只需要把所有经纬度整合成一个矩阵传给它,一次就能算出所有点到(90,90)的距离,速度会快N倍。
步骤如下:
- 先确保你加载了
geosphere包(distHaversine和distm都在这里):library(geosphere) - 把数据里的经纬度提取成一个两列的矩阵:
coords_matrix <- cbind(Current_Month$Lon, Current_Month$Lat) - 一次性计算所有点到目标坐标的距离:
all_distances <- distm(c(90, 90), coords_matrix, fun = distHaversine) - 生成你需要的
Nearby列:Current_Month$Nearby <- ifelse(all_distances < 1000, 1, all_distances)
这样操作下来,原本几小时的任务可能几分钟甚至几秒就搞定了——因为distm的底层是用高效的编译语言实现的,比R层面的循环快太多。
如果一定要用apply族函数(不推荐,效率提升有限)
如果你只是想试试apply的写法,那可以用sapply,但本质上还是逐行处理,效率和for循环差不多,聊胜于无:
Current_Month$Nearby <- sapply(1:nrow(Current_Month), function(i) { d <- distm(c(90, 90), c(Current_Month$Lon[i], Current_Month$Lat[i]), fun = distHaversine) ifelse(d < 1000, 1, d) })
额外小建议
如果你的需求只是标记“是否小于1000米”(比如1代表近,0代表远),那可以简化成:
Current_Month$Is_Nearby <- as.integer(all_distances < 1000)
这样得到的是0/1的标记列,更符合“标记”的语义,而且运算更快。
内容的提问来源于stack exchange,提问作者qwerty123
相关产品推荐
相关产品推荐

