如何用ggplot2绘制临床试验实际与预计招募曲线(日期X轴)
解决临床试验实际与预计招募对比图的直线叠加问题
你当前的问题出在geom_abline的参数设置上:x轴是日期格式,单位是天,但你直接用「每月20人」作为斜率,数值过大导致直线直接超出图表显示范围。下面给两种可行的修正方案:
方案一:修正geom_abline的斜率与截距
把每月招募人数换算成每日招募率,再结合起始日期的数值计算截距,确保直线和图表坐标轴匹配:
library(tibble) library(ggplot2) # 生成原始数据(这部分代码不变) patient_ids <- paste0("Patient", 1:50) recruitment_dates <- sample(seq(as.Date("2024-01-01"), as.Date("2024-12-31"), by = "day"), 50) patients <- tibble( Patient_ID = patient_ids, Recruitment_Date = recruitment_dates ) patients <- patients[order(patients$Recruitment_Date), ] patients$Recruitment_Order <- 1:nrow(patients) # 计算每日预计招募率:每月20人,按每月30天估算 daily_recruit_rate <- 20 / 30 # 计算截距:保证2024-01-01时预计招募人数为0 start_date_num <- as.numeric(as.Date("2024-01-01")) intercept_val <- -daily_recruit_rate * start_date_num # 绘图 ggplot(patients, aes(x = Recruitment_Date, y = Recruitment_Order)) + geom_point() + geom_abline(slope = daily_recruit_rate, intercept = intercept_val, color = "red", linetype = "dashed") + labs(x = "招募日期", y = "累计招募人数") + ggtitle("实际招募与预计招募对比")
方案二:用geom_line配合预计数据框(更直观推荐)
手动生成预计招募的完整时间序列数据,用折线图叠加,逻辑更清晰,也方便后续调整招募速率:
library(tibble) library(ggplot2) # 生成原始数据(这部分代码不变) patient_ids <- paste0("Patient", 1:50) recruitment_dates <- sample(seq(as.Date("2024-01-01"), as.Date("2024-12-31"), by = "day"), 50) patients <- tibble( Patient_ID = patient_ids, Recruitment_Date = recruitment_dates ) patients <- patients[order(patients$Recruitment_Date), ] patients$Recruitment_Order <- 1:nrow(patients) # 生成预计招募数据 start_date <- as.Date("2024-01-01") end_date <- as.Date("2024-12-31") # 生成每日日期序列 expected_dates <- seq(start_date, end_date, by = "day") # 计算每日累计预计招募人数 expected_total <- floor((as.numeric(expected_dates) - as.numeric(start_date) + 1) * (20/30)) expected_df <- tibble( Date = expected_dates, Expected_Recruitment = expected_total ) # 绘图 ggplot() + # 实际招募点 geom_point(data = patients, aes(x = Recruitment_Date, y = Recruitment_Order)) + # 预计招募折线 geom_line(data = expected_df, aes(x = Date, y = Expected_Recruitment), color = "red", linetype = "dashed") + labs(x = "招募日期", y = "累计招募人数") + ggtitle("实际招募与预计招募对比")
两种方案的区别:
- 方案一更简洁,适合固定速率的预计招募场景;
- 方案二更灵活,比如后续需要调整不同阶段的招募速率(如前3个月每月10人,之后每月25人),只需修改
expected_total的计算逻辑即可。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

