按日期及昼夜时段将双时点宽格式数据转换为长格式
按日期+昼夜时段统计住院患者数:宽转长及实现方案
需求说明
现有包含患者ID、住院起止时间的宽格式数据,需要按日期、昼夜时段(白天:8:00-17:00;夜间:17:00-次日8:00)统计各时段的在院患者总数,核心步骤是将双时点宽格式数据转换为包含所有覆盖时段的长格式数据,再进行聚合统计。
模拟数据
使用tidyverse和lubridate包生成可复现的模拟数据:
library(tidyverse) library(lubridate) set.seed(123) # 固定随机种子保证结果一致 df = tibble( id = c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"), start = sample(seq(as.POSIXct('2022-01-01'), as.POSIXct('2022-02-02'), by = "sec"), 10), end = sample(seq(as.POSIXct('2022-02-02'), as.POSIXct('2022-03-03'), by = "sec"), 10))
实现步骤
1. 定义时段拆分函数
编写函数将单个患者的住院时间段,拆分为其覆盖的所有日期-时段单元:
# 将住院起止时间拆分为覆盖的日期-昼夜时段 split_into_day_night <- function(start_time, end_time) { # 生成住院期间覆盖的所有日期 dates <- seq.Date(as.Date(start_time), as.Date(end_time), by = "day") # 遍历每个日期,判断是否覆盖该日期的白天/夜间 map_dfr(dates, function(date) { # 定义当日昼夜时段的时间边界 day_window <- interval(ymd_hms(paste(date, "08:00:00")), ymd_hms(paste(date, "17:00:00"))) night_window <- interval(ymd_hms(paste(date, "17:00:00")), ymd_hms(paste(date + 1, "08:00:00"))) # 判断住院时段与昼夜窗口是否有交集 cover_day <- int_overlaps(interval(start_time, end_time), day_window) cover_night <- int_overlaps(interval(start_time, end_time), night_window) # 生成有效时段记录 tibble( date = date, period = c(if(cover_day) "白天", if(cover_night) "夜间") ) }) }
2. 宽转长:生成所有覆盖时段记录
对每个患者应用拆分函数,将宽格式数据转换为包含所有日期-时段的长格式数据:
df_long <- df %>% rowwise() %>% mutate(period_records = list(split_into_day_night(start, end))) %>% unnest(period_records) %>% select(id, date, period)
3. 统计各时段患者数
使用group_by()和summarize()完成聚合统计,去重保证每个患者在同一时段只被计数一次:
patient_stats <- df_long %>% group_by(date, period) %>% summarize(total_patients = n_distinct(id)) %>% ungroup() # 查看结果示例 head(patient_stats)
结果说明
最终得到的patient_stats数据框包含三列:date(日期)、period(时段:白天/夜间)、total_patients(该时段在院患者总数),完全满足需求。
内容的提问来源于stack exchange,提问作者st4co4
相关产品推荐
相关产品推荐

