如何将DataFrame按时间关联事件分组并转为宽格式?
解决方案:事件分组与宽格式转换
核心思路
要实现需求,需先将宽格式数据转为长格式,按受试者ID分组处理时间数据:
- 对每个ID的非NA时间值排序
- 按时间差>0.25的规则划分事件组
- 每个事件组取最小时间值,再转回宽格式生成
event_1至event_X列 - 修正原代码中事件数量判断的逻辑错误
完整代码实现
首先加载所需工具包:
library(tidyverse)
步骤1:数据格式转换与事件分组
# 1. 将宽格式转为长格式,过滤缺失值并排序 df_long <- df %>% pivot_longer(cols = starts_with("Time_to_code_"), names_to = "data_source", values_to = "time_to_code") %>% filter(!is.na(time_to_code)) %>% arrange(ID, time_to_code) # 2. 按ID划分事件组,每组取最小时间 df_events <- df_long %>% group_by(ID) %>% # 计算相邻时间差,标记新事件组的起点 mutate(time_diff = time_to_code - lag(time_to_code), event_group = cumsum(ifelse(is.na(time_diff), FALSE, time_diff > 0.25)) + 1) %>% # 每个事件组保留最小时间 group_by(ID, event_group) %>% summarise(event_time = min(time_to_code), .groups = "drop") %>% # 生成事件列名(event_1, event_2...) mutate(event_col = paste0("event_", event_group)) %>% # 转回宽格式 pivot_wider(id_cols = ID, names_from = event_col, values_from = event_time)
步骤2:合并原数据并修正事件判断列
# 3. 与原DataFrame合并,补全事件列 df_final <- df %>% left_join(df_events, by = "ID") %>% # 修正"是否多事件"判断 mutate(Multiple_Injuries = case_when( rowSums(!is.na(select(., starts_with("event_")))) >= 2 ~ "Yes", TRUE ~ "No" ), # 修正"事件数量"计算 Number_of_injuries = rowSums(!is.na(select(., starts_with("event_")))) )
关键说明
- 事件分组逻辑:
- 对每个ID的时间排序后,当相邻时间差>0.25时,开启新的事件组
- 第一个时间自动归为
event_1,后续时间根据差值得出所属组
- 原代码问题修正:
- 原
Number_of_injuries错误返回非NA列数,现在改为统计实际事件组数量 - 原
Multiple_Injuries逻辑仅需验证事件数≥2即可,无需依赖时间差统计
- 原
- 结果完整性:
- 未发生多事件的ID,
event_2及后续列会显示NA,不影响原数据结构
- 未发生多事件的ID,
内容的提问来源于stack exchange,提问作者DW1310
相关产品推荐
相关产品推荐

