R语言12万行相机照片按站点时间分箱的代码性能优化问题
代码慢的核心原因
你的写法用了两层for循环,每次修改都要全表遍历匹配数据,12万行数据反复扫描上百次,自然耗时久。而且和data.table按引用修改的特性不匹配,生成了很多没必要的副本,额外拖慢了速度。
优化方案(覆盖两类需求)
场景1:按运维周期自动分箱
用data.table原生的非等值连接实现,全程没有R层循环,12万行数据跑完全程最多几秒,代码如下:
library(data.table) # 先确认两张表都是data.table格式 setDT(visits_tbl) setDT(photo_tbl) # 第一步:给visits_tbl批量生成每个运维周期的起始时间和bin名称 visits_tbl[order(year_unit_station, service_end_dttm), `:=`( # 上一次运维结束时间作为当前周期的起始,首次用安装时间补全 bin_start = shift(service_end_dttm, fill = first(install_dttm)), bin_name = paste0(year_unit_station, "_", seq_len(.N)) ), by = year_unit_station] # 第二步:一次匹配完成所有照片的分箱打标 photo_tbl[visits_tbl, bin_name := i.bin_name, on = .( year_unit_station, Creation_Datetime > bin_start, Creation_Datetime < service_end_dttm )]
如果要保留恰好落在运维时间点的照片,把连接条件里的>/<改成>=/<=即可。
场景2:自定义时间粒度分箱
如果需要按固定时长(比如15分钟、1小时)分箱,直接用时间切割函数即可,粒度可以灵活调整:
# 自定义时间粒度,支持"1 mins"、"1 hour"、"1 day"等任意写法 time_grain <- "15 mins" photo_tbl[, bin_name_custom := paste0(year_unit_station, "_", cut(Creation_Datetime, breaks = time_grain))] # 如果需要过滤掉相机部署前、撤场后的无效照片,关联visits_tbl的安装、撤场时间筛选即可
额外优化小提示
- 提前给表的关联字段加索引,速度还能再提升:
setkey(visits_tbl, year_unit_station, service_end_dttm) setkey(photo_tbl, year_unit_station, Creation_Datetime) - 不要用dplyr的filter或者base的
within和data.table混用,data.table原生语法直接修改原表,不会生成冗余副本,内存占用会小很多
内容的提问来源于stack exchange,提问作者Jordan
相关产品推荐
相关产品推荐

