R语言处理GPS数据统计A点到B点的有效完成行程次数
R语言GPS卡车行程统计实现方案
前置说明
你原有区域判断代码存在逻辑错误:df$Latitude<=45.50 & df$Latitude>=45.55 永远返回FALSE,因为45.55大于45.50,以下代码已修正该问题。
实现逻辑
- 第一步:格式化时间字段,按时间升序排序数据
- 第二步:标记GPS点所属区域(A区/B区/非目标区)
- 第三步:识别连续停留事件,合并同一区域连续GPS点为单个停留事件,支持自定义最小停留时长过滤
- 第四步:匹配连续的A区停留→B区停留序列,统计为一次完整行程
完整可运行代码
# 加载所需包,未安装的话先运行 install.packages(c("dplyr", "lubridate")) 安装 library(dplyr) library(lubridate) # 仅用于简化时间格式化,也可以替换为base R的as.POSIXct实现 # ---------------------- 1. 数据预处理 ---------------------- # 示例数据导入,实际使用时替换为你的数据读取代码 df <- data.frame( `Record Time` = c("07/04/2020 10:00:00", "07/04/2020 10:01:00", "07/04/2020 10:02:00", "07/04/2020 10:15:00", "07/04/2020 10:16:00", # B区停留示例 "07/04/2020 12:00:00", "07/04/2020 12:01:00", # 第二次A区停留 "07/04/2020 12:30:00", "07/04/2020 12:31:00"), # 第二次B区停留 Duration = c("00:00.00", "00:01.00", "00:02.00", "00:15.00", "00:16.00", "00:00.00", "00:01.00", "00:30.00", "00:31.00"), Longitude = c(08.32436, 08.32436, 08.32436, 8.42436, 8.42436, # B区经度示例 08.32436, 08.32436, 8.42436, 8.42436), Latitude = c(45.53638, 45.53638, 45.53638, 45.63638, 45.63638, # B区纬度示例 45.53638, 45.53638, 45.63638, 45.63638), Altitude = c(85.4, 85.4, 85.4, 92.1, 92.1, 85.4, 85.4, 92.1,92.1), check.names = F ) # 转换时间格式,按时间排序 df$`Record Time` <- dmy_hms(df$`Record Time`) # 不用lubridate的话替换为:df$`Record Time` <- as.POSIXct(df$`Record Time`, format="%d/%m/%Y %H:%M:%S") df <- df %>% arrange(`Record Time`) # ---------------------- 2. 定义区域规则 ---------------------- # 自定义A、B区域范围,按实际需求修改 A_LON_MIN <- 8.30; A_LON_MAX <- 8.35 A_LAT_MIN <- 45.50; A_LAT_MAX <- 45.55 A_ALT_MIN <- 85.35; A_ALT_MAX <- 85.45 B_LON_MIN <- 8.40; B_LON_MAX <- 8.45 B_LAT_MIN <- 45.60; B_LAT_MAX <- 45.65 B_ALT_MIN <- 92.05; B_ALT_MAX <- 92.15 # 标记所属区域 df$region <- NA df$region[df$Longitude >= A_LON_MIN & df$Longitude <= A_LON_MAX & df$Latitude >= A_LAT_MIN & df$Latitude <= A_LAT_MAX & df$Altitude >= A_ALT_MIN & df$Altitude <= A_ALT_MAX] <- "A" df$region[df$Longitude >= B_LON_MIN & df$Longitude <= B_LON_MAX & df$Latitude >= B_LAT_MIN & df$Latitude <= B_LAT_MAX & df$Altitude >= B_ALT_MIN & df$Altitude <= B_ALT_MAX] <- "B" # ---------------------- 3. 识别连续停留事件 ---------------------- # 用rle识别连续相同区域的块 rle_res <- rle(df$region) # 生成事件ID df$event_id <- rep(seq_along(rle_res$lengths), rle_res$lengths) # 统计每个停留事件的信息 stay_events <- df %>% filter(!is.na(region)) %>% # 过滤非目标区域的点 group_by(event_id, region) %>% summarise( start_time = min(`Record Time`), end_time = max(`Record Time`), stay_duration = difftime(end_time, start_time, units = "mins"), # 停留时长,单位分钟 .groups = "drop" ) # 可选:过滤过短的停留,比如停留小于1分钟的不算,不需要的话注释掉这行即可 stay_events <- stay_events %>% filter(stay_duration >= 0) # 0表示不过滤,按需求调整 # ---------------------- 4. 匹配A→B行程 ---------------------- journeys <- data.frame() if(nrow(stay_events) >=2 ){ for(i in 2:nrow(stay_events)){ # 前一个事件是A,当前事件是B,匹配为一次行程 if(stay_events$region[i-1] == "A" && stay_events$region[i] == "B"){ journeys <- rbind(journeys, data.frame( journey_id = nrow(journeys)+1, start_time = stay_events$start_time[i-1], end_time = stay_events$end_time[i] )) } } } # ---------------------- 5. 输出结果 ---------------------- cat(paste0("Amount journeys: ", nrow(journeys), "\n")) if(nrow(journeys)>0){ # 格式化时间为HH:MM,和需求示例一致 journeys$Start <- format(journeys$start_time, "%H:%M") journeys$End <- format(journeys$end_time, "%H:%M") print(journeys %>% select(journey_id, Start, End), row.names = F) }
输出示例
运行上述示例数据后输出如下:
Amount journeys: 2 journey_id Start End 1 10:00 10:16 2 12:00 12:31
如果需要计算跨天的行程,修改format的时间格式即可,比如加日期参数"%d/%m/%Y %H:%M"。
内容的提问来源于stack exchange,提问作者mcfly
相关产品推荐
相关产品推荐

