ggplot2指定研究ID点标红、其余按疫苗分组着色及图层调整
实现方案
该效果完全可以在ggplot2中实现,解决目标ID点被遮挡的核心逻辑是利用ggplot2图层从上到下叠加的特性:后声明的geom图层会绘制在更上层,将目标ID的点单独拆分到第二个geom_jitter图层即可解决遮挡问题,同时代码逻辑更清晰,更适配批量生成百余位参与者个性化图表的需求。
优化后代码
# 提前定义目标研究ID,批量生成时仅需修改该变量即可 target_sample_id <- "V1" df %>% mutate(Group = as.factor(Group)) %>% mutate(Timepoint = fct_relevel(Timepoint, c("Pre-vaccine", "< 3.5 weeks after first", "3-6 weeks after first", "6-12 weeks after first", "> 12 weeks after first", "< 3 weeks after second", "3-6 weeks after second", "6-12 weeks after second", "> 12 weeks after second"))) %>% droplevels() %>% filter(Assay == "Antibody levels" & Group %in% c(0,1,2,3,4)) %>% ggplot(aes(Timepoint, Concentration)) + # 第一层:绘制所有非目标ID的点,按Group分组着色 geom_jitter(position = position_jitter(width = 0.0001), aes(fill = Group), data = ~filter(.x, !str_detect(Sample, target_sample_id)), pch = 21, size = 2.5) + # 第二层:单独绘制目标ID的点,固定为红色,自动显示在最上层 geom_jitter(position = position_jitter(width = 0.0001), fill = "red", data = ~filter(.x, str_detect(Sample, target_sample_id)), pch = 21, size = 2.5) + scale_y_log10(labels = scales::comma, limits = c(10,10000000), breaks = breaks, minor_breaks = minor_breaks) + theme_classic()+ labs(title = "Antibody levels", x = "", y = "Concentration (AU/ml)") + annotation_logticks(base = 10, sides = "l") + # 色板仅需匹配Group的取值即可,无需额外适配ID值 scale_fill_manual(values = pal) + theme(plot.title = element_text(hjust = 0.5), axis.text.y = element_text(face = "bold"), axis.text.x = element_text(angle = 45, hjust = 1, face = "bold"), legend.position = "none")
改动说明
- 新增单独的目标ID变量
target_sample_id,批量生成不同参与者的图表时仅需修改该变量即可,无需调整绘图逻辑 - 将原单个geom_jitter拆分为两个图层:先绘制所有非目标参与者的点,再绘制目标参与者的点,从底层逻辑上避免了目标点被遮挡的问题
- 简化了fill映射逻辑,无需在映射中写条件判断,原有
pal色板无需调整即可直接使用 - 两层geom_jitter使用完全一致的抖动参数,保证点的分布位置和原有逻辑完全一致
可选轻量修改方案
如果不想拆分图层,也可以通过调整数据行顺序解决,在droplevels()后增加排序逻辑,将目标ID的行放在数据框末尾,同一图层内ggplot会按行顺序绘制,末尾行的点会显示在上方:
droplevels() %>% mutate(is_target = str_detect(Sample, target_sample_id)) %>% arrange(is_target) %>% # 非目标行在前,目标行在后
内容的提问来源于stack exchange,提问作者Liam Golding
相关产品推荐
相关产品推荐

