如何计算带时间戳的连续GPS点位间距离(含缺失值处理)
解决方案
依赖包
首先安装并加载所需工具包:
# 首次使用先执行安装 install.packages(c("dplyr", "lubridate", "geosphere")) # 加载依赖 library(dplyr) library(lubridate) library(geosphere)
处理逻辑与代码
步骤1:定义时间规则校验函数
首先封装函数判断连续两个点位的时间间隔是否符合采集规则:
check_time_rule <- function(prev_time, curr_time) { # 计算时间差(单位:小时) gap_hour <- as.duration(curr_time - prev_time) / dhours(1) prev_h <- hour(prev_time) curr_h <- hour(curr_time) # 3种合法间隔场景 # 场景1:14:00~次日04:00区间内的每小时采集 scene1 <- gap_hour == 1 && curr_h %in% c(14:23, 0:4) # 场景2:前一个点位是04:00,下一个是当日10:00,间隔6小时 scene2 <- gap_hour == 6 && prev_h == 4 && curr_h == 10 # 场景3:前一个点位是10:00,下一个是当日14:00,间隔4小时 scene3 <- gap_hour == 4 && prev_h == 10 && curr_h == 14 return(scene1 | scene2 | scene3) }
步骤2:数据清洗与距离计算
对原始数据分组、校验后计算距离:
# df替换为你的原始数据框 result <- df %>% # 标记无效行:采集异常、经纬度为空都判定为无效 mutate(valid_row = Info == "3D" & !is.na(Latitude) & !is.na(Longitude)) %>% # 生成连续有效序列分组ID:遇到无效行则分组ID+1,跨错误点位不会合并计算 mutate(group_id = cumsum(!valid_row)) %>% # 过滤无效行,仅保留有效点位参与计算 filter(valid_row) %>% # 确保数据按时间升序排列 arrange(DateTime) %>% # 按分组独立计算每组内的相邻距离 group_by(group_id) %>% mutate( # 校验和前一个点位的时间间隔是否符合规则 conform_rule = mapply(check_time_rule, lag(DateTime), DateTime), # 计算哈弗辛距离(单位:米),不符合规则/组内第一个点位的距离为NA distance_m = ifelse( conform_rule, distHaversine( cbind(lag(Longitude), lag(Latitude)), cbind(Longitude, Latitude) ), NA_real_ ) ) %>% ungroup() %>% # 按需删除中间辅助列 select(-valid_row, -conform_rule)
结果说明
输出的result数据框中:
group_id标记了点位所属的连续有效序列,相同ID的点位属于同一段没有采集中断的有效数据distance_m为和前一个相邻有效点位的距离,单位为米;取值为NA代表该点位是当前序列的第一个点,或和前一个点位的时间间隔不符合采集规则- 采集错误的点位会被自动过滤,前后有效点位不会跨错误点位计算距离
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

