R语言按id分组计算相邻dive/surface行duration占比(处理缺失配对)
实现方法
核心思路:利用dplyr的行偏移函数lead()/lag()逐行匹配相邻的dive-surface事件对,避免手动取子集导致的长度不匹配报错,无有效配对的行自动填充NA。
依赖加载
library(dplyr)
场景1:比例结果存储在dive行(匹配对应行的下一个surface)
df_res <- df %>% group_by(id) %>% mutate( # 提取当前行紧邻的下一行事件类型、时长,分组末尾无下一行时默认填NA next_e = lead(event, default = NA_character_), next_dur = lead(duration, default = NA_real_), # 仅当前行是dive、下一行是surface时按公式计算,其余情况填NA proportion = case_when( event == "dive" & next_e == "surface" ~ next_dur/(duration + next_dur), TRUE ~ NA_real_ ) ) %>% # 删除临时辅助列 select(-next_e, -next_dur) %>% ungroup()
场景2:比例结果存储在surface行(匹配初始期望输出结构)
如果需要把计算结果放在配对的surface行(和给出的初始输出示例结构一致),改用lag()取上一行值判断即可:
df_res_surface <- df %>% group_by(id) %>% mutate( # 提取当前行紧邻的上一行事件类型、时长,分组开头无上一行时默认填NA last_e = lag(event, default = NA_character_), last_dur = lag(duration, default = NA_real_), # 仅当前行是surface、上一行是dive时按公式计算,其余情况填NA proportion = case_when( event == "surface" & last_e == "dive" ~ duration/(last_dur + duration), TRUE ~ NA_real_ ) ) %>% select(-last_e, -last_dur) %>% ungroup()
报错原因说明
之前代码运行报错的核心原因是:分组内直接用DurationMin[What == "Surface"]取子集时,遇到dive后无对应surface的分组,取到的子集长度为0,和mutate要求的「计算结果长度需等于分组行数或长度为1」的规则冲突,所以抛出长度不匹配错误。
上述逐行偏移判断的写法完全规避了这个问题:
- 自动按原始行序匹配紧邻的事件对,不会跨非相邻事件配对
- 分组边界、事件不匹配的场景自动返回NA,不会出现长度为0的计算结果
- 测试提供的示例数据集时,末尾无对应surface的dive行、连续dive行的proportion都会自动填充NA,不会中断运行。
内容的提问来源于stack exchange,提问作者Caroline Portal
相关产品推荐
相关产品推荐

