R语言查找动物轨迹数据中满足连续3天登岸条件的首个行
问题解决方案:标记首个满足后续连续3天有登岸记录的行
核心问题分析
你原有代码的核心错误点:
- 生成
ymd日期列时错误取了第一行的日期赋值给所有行,导致所有记录的日期完全相同,后续按日期分组的统计逻辑完全失效 - 连续时长计算逻辑不符合需求,你需要的是自然日维度的连续3天每日有登岸,不是小时维度的连续登岸时长
解决步骤
- 第一步:修正日期列生成逻辑,正确提取每条记录对应的自然日
- 第二步:按个体+自然日聚合,得到每日是否有登岸的标记
- 第三步:用滑动窗口计算每个日期是否满足「后续连续3天每日均有登岸」的条件
- 第四步:将满足条件的最早日期关联回原小时级数据表,标记首个符合要求的行
完整可运行代码
依赖包加载
library(tidyverse) library(lubridate) library(slider) # 用于滑动窗口计算,兼容tidyverse语法
示例数据构造(和你提供的完全一致)
set.seed(13) n <- 100 dat <- data.frame(id = rep(1:5, each = 10), datetime=seq(as.POSIXct("2020-12-26 00:00:00"), as.POSIXct("2020-12-30 3:00:00"), by = "hour"), land = sample(0:1, n, replace = TRUE))
数据预处理
# 正确提取每条记录的自然日 dat <- dat %>% mutate(ymd = as_date(datetime)) %>% arrange(id, datetime)
按日聚合得到登岸标记
# 按个体+日期聚合,标记当日是否至少有1次登岸 daily_land_flag <- dat %>% group_by(id, ymd) %>% summarise(daily_has_land = as.integer(sum(land, na.rm = T) > 0), .groups = "drop")
滑动窗口筛选符合连续3天要求的最早日期
valid_dates <- daily_land_flag %>% group_by(id) %>% arrange(ymd) %>% # 滑动窗口大小为3,判断当前日期+后2天是否每天都有登岸记录 mutate(is_valid = slide_lgl(daily_has_land, ~all(.x == 1), .after = 2, .complete = T)) %>% ungroup() %>% filter(is_valid == T) %>% # 取每个个体最早的满足条件的起始日期 group_by(id) %>% slice_min(ymd, n = 1) %>% select(id, valid_start_date = ymd) %>% ungroup()
关联回原表标记目标行
final_dat <- dat %>% left_join(valid_dates, by = "id") %>% group_by(id) %>% # target_flag为1的行就是你要找的首个符合要求的行 mutate(target_flag = as.integer(ymd == valid_start_date & row_number(ymd) == 1)) %>% ungroup()
结果验证
# 查看所有标记的目标行 final_dat %>% filter(target_flag == 1) %>% select(id, datetime, land)
内容的提问来源于stack exchange,提问作者NorthLattitude
相关产品推荐
相关产品推荐

