如何将患者治疗首尾日期行扩展为连续日期序列?
实现治疗周期日期展开的R方案
原始数据准备
首先修正原始数据的类型问题(Day列需转为数值型才能生成连续序列):
a <- as.data.frame(matrix(c("1", "1", "1", "1", "2", "2", "A first day", "A last day", "B first day", "B last day", "A first day", "A last day", 3, 5, 10, 14, 2, 5), ncol = 3)) colnames(a) = c("Patient", "Treatment", "Day") a$Day <- as.numeric(a$Day) # 转换Day列为数值型
原始数据结构:
| Patient | Treatment | Day |
|---|---|---|
| 1 | A first day | 3 |
| 1 | A last day | 5 |
| 1 | B first day | 10 |
| 1 | B last day | 14 |
| 2 | A first day | 2 |
| 2 | A last day | 5 |
方法一:使用tidyverse工具链(推荐)
通过dplyr做数据清洗,tidyr做格式转换,步骤清晰易读:
library(tidyverse) # 1. 提取治疗标识和日期类型,转换为宽格式 a_clean <- a %>% mutate( Treatment = str_sub(Treatment, 1, 1), # 提取A/B治疗标识 Date_type = ifelse(str_detect(Treatment, "first"), "first", "last") # 区分起始/结束日 ) %>% pivot_wider( idvars = c("Patient", "Treatment"), names_from = Date_type, values_from = Day ) # 2. 生成连续日期序列并展开为行 final_df <- a_clean %>% rowwise() %>% mutate(Day = list(seq(first, last, by = 1))) %>% # 生成周期内的所有日期 unnest(Day) %>% # 将列表展开为单独行 select(Patient, Treatment, Day) %>% # 保留目标字段 arrange(Patient, Treatment, Day) # 按患者、治疗类型、日期排序 print(final_df)
方法二:使用Base R实现
无需额外安装包,纯基础R代码完成:
# 1. 提取关键信息 a$Treatment <- substr(a$Treatment, 1, 1) # 提取A/B治疗标识 a$Date_type <- ifelse(grepl("first", a$Treatment), "first", "last") # 标记日期类型 # 2. 转换为宽格式,将起始/结束日放在同一行 wide_df <- reshape( a, idvar = c("Patient", "Treatment"), timevar = "Date_type", direction = "wide" ) colnames(wide_df) <- c("Patient", "Treatment", "first_day", "last_day") # 3. 遍历每行生成日期序列,合并为最终数据框 final_list <- lapply(1:nrow(wide_df), function(row_idx) { current_row <- wide_df[row_idx, ] days_seq <- seq(current_row$first_day, current_row$last_day, by = 1) data.frame( Patient = current_row$Patient, Treatment = current_row$Treatment, Day = days_seq ) }) final_df <- do.call(rbind, final_list) final_df <- final_df[order(final_df$Patient, final_df$Treatment, final_df$Day), ] print(final_df)
最终输出结果
两种方法都会生成目标格式的数据框:
| Patient | Treatment | Day |
|---|---|---|
| 1 | A | 3 |
| 1 | A | 4 |
| 1 | A | 5 |
| 1 | B | 10 |
| 1 | B | 11 |
| 1 | B | 12 |
| 1 | B | 13 |
| 1 | B | 14 |
| 2 | A | 2 |
| 2 | A | 3 |
| 2 | A | 4 |
| 2 | A | 5 |
内容的提问来源于stack exchange,提问作者Wandering_geek
相关产品推荐
相关产品推荐

