使用lag()对比DataFrame行数据实现GPS POI识别的代码问题咨询
代码问题分析
- 核心逻辑错误:
lag()函数的使用完全不符合需求lag()只能提取同一分组下上一条相邻记录的字段值,你要实现的是匹配「当前时间+3分钟后30秒区间内的任意记录」,和相邻上一行没有任何关系。你代码里的min3 <= lag(min3)条件完全没有用到你设置的时间偏移逻辑去匹配对应时间的记录,只是比较相邻两行的min3值,不管你把偏移量改成3分钟还是1小时,相邻行的判断逻辑都不会变,所以结果完全一致。 - 条件逻辑不符合需求
你当前的stay判断逻辑只是校验相邻两行的经纬度是否一致、且当前行的min3小于等于上一行的min3(按时间升序排列的话这个条件几乎永远不成立),完全没有实现「校验3分钟后区间内的记录经纬度是否一致」的核心需求。
正确实现思路
你需要对每一条记录,匹配同一id下,时间落在[当前Timestamp + 180秒, 当前Timestamp + 210秒]区间内的所有记录,判断是否存在经纬度和当前记录一致的条目,存在则说明该位置满足停留要求,属于候选POI。
示例实现代码
针对中小数据量可以用dplyr的行式处理逻辑:
library(dplyr) library(purrr) POI_gps <- locations_gps %>% group_by(id) %>% arrange(Timestamp, .by_group = TRUE) %>% mutate( # 定义匹配的时间区间:+3分钟 到 +3分30秒 start_match = Timestamp + 3*60, end_match = Timestamp + 3*60 +30 ) %>% rowwise() %>% mutate( # 校验区间内是否有相同经纬度的记录 stay = any( locations_gps$id == id & locations_gps$Timestamp >= start_match & locations_gps$Timestamp <= end_match & locations_gps$lat == lat & locations_gps$long == long ) ) %>% ungroup() %>% filter(stay == TRUE) %>% distinct(id, lat, long)
如果数据量较大(十万条以上),推荐使用data.table的非等值连接实现,性能会高很多:
library(data.table) setDT(locations_gps) # 按id和时间排序 setkey(locations_gps, id, Timestamp) # 生成待匹配的区间表 match_dt <- locations_gps[, .(id, Timestamp, lat, long, start_match = Timestamp + 180, end_match = Timestamp + 210)] # 非等值连接匹配区间内的记录 joined <- match_dt[locations_gps, on = .(id, start_match <= Timestamp, end_match >= Timestamp), nomatch = 0] # 筛选经纬度一致的记录,去重得到POI POI_gps <- unique(joined[lat == i.lat & long == i.long, .(id, lat, long)])
内容的提问来源于stack exchange,提问作者Madwolf
相关产品推荐
相关产品推荐

