基于R语言绘制多患者用药时间线图谱的技术求助
解决多患者用药时间线图谱中点重叠覆盖问题
在绘制多患者用药时间线时,当p_start/p_end与mid_point_dates坐标重叠时,会出现点被覆盖的情况,导致部分关键时间点无法清晰展示。以下是两种可行的解决方案:
方案1:调整图层顺序与点样式
通过控制图层绘制顺序,将需要突出的中间时间点放在最上层,同时给p_start/p_end使用空心带边框的形状,即使重叠也能透过空心看到下方内容。
修改后的代码:
# Load required libraries library(ggplot2) library(lubridate) # Define the data id = c(214441, 214441, 214441, 214444, 214444, 214446) med_name = c("morphine", "codeine", "diamorphine", "codeine", "morphine", "drug_X") p_start = ymd_hms("2010-04-29 12:31:58", "2010-04-29 12:31:58", "2010-04-29 12:31:58", "2010-04-25 12:31:58", "2010-04-25 12:31:58", "2010-04-25 12:31:58") p_end = ymd_hms("2010-05-19T14:05:00Z", "2010-05-19T14:05:00Z", "2010-05-19 12:31:58", "2010-05-27 12:31:58", "2010-05-27 12:31:58", "2010-05-20 12:31:58") mid_point_dates = ymd_hms(c("2010-05-09T14:05:00Z", "2010-04-29T14:05:00Z", "2010-05-01T12:52:14Z", "2010-05-13T14:04:00Z", "2010-05-03T14:04:00Z", "2010-04-30T10:34:27Z")) # Create a data frame df <- data.frame(id, med_name, p_start, p_end, mid_point_dates) # Define the y-axis categories id_categories <- unique(df$id) ggplot(df, aes(y = id)) + # 先绘制用药时间段线段 geom_segment(aes(x = p_start, xend = p_end, yend = id), size = 1.5, color = "grey80") + # 绘制p_start(空心圆形)和p_end(空心方形) geom_point(aes(x = p_start), size = 4, shape = 21, fill = "white", color = "black") + geom_point(aes(x = p_end), size = 4, shape = 22, fill = "white", color = "black") + # 最后绘制中间时间点(实心,覆盖在上方) geom_point(aes(x = mid_point_dates, color = med_name, shape = med_name), size = 3) + # 样式配置 scale_color_manual(values = c("purple", "green", "orange", "blue"), name = "Medication") + scale_shape_manual(values = c(17, 15, 16, 2), name = "Medication") + scale_y_discrete(limits = id_categories) + labs(title = "Medication Timeline", x = "Date", y = "Patient ID") + theme_minimal()
方案2:重构数据为长格式(推荐)
将所有时间点(start、mid、end)整合到同一列并标记类型,统一管理图层和样式,后续扩展更灵活。
代码示例:
# Load required libraries library(ggplot2) library(lubridate) library(tidyr) # Define the data id = c(214441, 214441, 214441, 214444, 214444, 214446) med_name = c("morphine", "codeine", "diamorphine", "codeine", "morphine", "drug_X") p_start = ymd_hms("2010-04-29 12:31:58", "2010-04-29 12:31:58", "2010-04-29 12:31:58", "2010-04-25 12:31:58", "2010-04-25 12:31:58", "2010-04-25 12:31:58") p_end = ymd_hms("2010-05-19T14:05:00Z", "2010-05-19T14:05:00Z", "2010-05-19 12:31:58", "2010-05-27 12:31:58", "2010-05-27 12:31:58", "2010-05-20 12:31:58") mid_point_dates = ymd_hms(c("2010-05-09T14:05:00Z", "2010-04-29T14:05:00Z", "2010-05-01T12:52:14Z", "2010-05-13T14:04:00Z", "2010-05-03T14:04:00Z", "2010-04-30T10:34:27Z")) # 转换为长格式数据 df <- data.frame(id, med_name, p_start, p_end, mid_point_dates) %>% pivot_longer(cols = c(p_start, p_end, mid_point_dates), names_to = "point_type", values_to = "date") # 定义y轴类别 id_categories <- unique(df$id) ggplot(df, aes(y = id)) + # 绘制用药时间段线段(从去重后的宽格式数据取) geom_segment(data = distinct(df, id, med_name, p_start, p_end), aes(x = p_start, xend = p_end, yend = id), size = 1.5, color = "grey80") + # 先绘制start/end点 geom_point(data = filter(df, point_type %in% c("p_start", "p_end")), aes(x = date, shape = point_type), size = 4, fill = "white", color = "black") + # 最后绘制中间时间点 geom_point(data = filter(df, point_type == "mid_point_dates"), aes(x = date, color = med_name, shape = med_name), size = 3) + # 样式配置 scale_color_manual(values = c("purple", "green", "orange", "blue"), name = "Medication") + scale_shape_manual(values = c(p_start=21, p_end=22, morphine=17, codeine=15, diamorphine=16, drug_X=2), name = "Point Type") + scale_y_discrete(limits = id_categories) + labs(title = "Medication Timeline", x = "Date", y = "Patient ID") + theme_minimal()
关键说明
- 图层顺序:ggplot2中后添加的图层会绘制在上方,将需要突出的中间时间点放在最后,就能覆盖在start/end点之上。
- 形状选择:带填充的空心形状(如
shape=21/22)可保留底层视觉信息,实心形状(如15/16/17)用于突出中间时间点。 - 长格式数据:统一管理所有时间点,减少重复代码,后续新增点类型时更易扩展。
内容的提问来源于stack exchange,提问作者db2020
相关产品推荐
相关产品推荐

