You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:27:03