cumsum、difftime、lag函数使用问题:连续yes行时间差计算异常
解决连续buffer="yes"序列的停留时长计算问题
你的数据集包含buffer(标记GPS点是否在缓冲区,值为yes/no)、DateTime(GPS点时间)、dt1(缓冲区停留时长)三列,按tripID分组处理。目前单个yes行能正确计算与前一行的时间差,但连续yes行的dt1返回NA,你需要在连续yes序列的最后一行填入该序列首尾GPS点的时间差。
原代码里的cumsum逻辑不对——它会给每个连续yes行都累加时间差,而不是只在最后一行生成首尾时间差。可以用以下方法修正:
解决方案代码
library(dplyr) library(data.table) # 用到rleid函数识别连续序列 trips_with_buffer_2016_df <- trips_with_buffer_2016_df %>% group_by(tripID) %>% # 生成连续buffer状态的分组ID,每个连续的yes/no序列对应唯一id mutate(buffer_group = rleid(buffer)) %>% group_by(tripID, buffer_group) %>% mutate( # 计算当前buffer块的首尾时间差 block_duration = as.numeric(difftime(max(DateTime), min(DateTime), units = "mins")), # 标记当前行是否是该buffer块的最后一行 is_last_row = row_number() == n(), # 计算单个yes行的时间差(和前一行的间隔) single_yes_duration = ifelse(buffer == "yes" & n() == 1, as.numeric(difftime(DateTime, lag(DateTime), units = "mins")), NA_real_) ) %>% ungroup() %>% # 最终赋值dt1:连续yes的最后一行用block_duration,单个yes用single_yes_duration,其余为NA mutate( dt1 = case_when( buffer == "yes" & is_last_row & n() > 1 ~ block_duration, buffer == "yes" & n() == 1 ~ single_yes_duration, TRUE ~ NA_real_ ) ) %>% # 清理临时列 select(-buffer_group, -block_duration, -is_last_row, -single_yes_duration) %>% # 重新按tripID分组(如果后续需要) group_by(tripID)
代码说明
rleid(buffer):给每个连续的yes或no序列分配唯一分组ID,比如连续3个yes会被分到同一个buffer_group里。- 按
tripID + buffer_group分组:针对每个连续的buffer状态块计算首尾时间差,同时标记块内的最后一行。 case_when逻辑:- 当是连续
yes块的最后一行时,填入该块的首尾时间差 - 当是单个
yes行时,保留原逻辑计算与前一行的时间差 - 其他情况(
no行或连续yes的中间行)填NA
- 当是连续
这样就能精准实现你要的效果:单个yes行填与前一行的时间差,连续yes序列仅最后一行填首尾时间差,其余yes行和所有no行的dt1为NA。
内容的提问来源于stack exchange,提问作者Ioannis
相关产品推荐
相关产品推荐

