如何使用R在时间进程图中添加各组各时间点的观测数标注
ggplot2时间进程图标注分组各时间点样本量实现方案
你原有代码的geom_text层存在逻辑问题:固定y=0会让标签全部堆叠在x轴底部,直接映射原始lac列作为标签会输出所有原始观测的乳酸值,无法得到分组样本量标注。以下是两种可直接复用的实现方式:
方法1:原生stat_summary层自动统计(无需提前处理数据)
完全适配你现有代码的统计逻辑,不需要提前汇总数据,直接替换原有错误的geom_text层即可,修正后的完整代码如下:
ggplot(df, aes(x=time_nrp, y=lac, color=as.factor(outcome)))+ geom_point(stat="summary", fun=mean, size=4)+ geom_line(stat="summary", fun=mean, aes(group=as.factor(outcome)))+ stat_summary(fun.data=mean_se, geom="errorbar", width=0.01)+ # 新增样本量标注层,自动按分组+时间点计数 stat_summary( fun = length, geom = "text", aes(label = after_stat(n)), vjust = -1.2, # 调整垂直位置,标签放在均值点上方,避免遮挡图形 size = 5, show.legend = FALSE # 避免文本层额外生成冗余图例 )+ xlab("NRP Time (hours)")+ ylab("Lactate (mmol/l)")+ theme_bw()+ ggtitle("Panel A")+ theme(plot.title = element_text(hjust=0.5))+ theme(text=element_text(family="Helvetica", size=20))+ scale_color_manual(name="Outcome", breaks=c("0", "1"), labels=c("Negative", "Positive"), values = c("#E12000", "#002F80"))
针对你提供的示例测试数据(变量名为group/time/lactate),适配后的可运行测试代码:
# 读入示例数据 df_demo <- read.table(text = "id group time lactate 1 A 1 1.2 1 A 2 1.1 1 A 3 1.3 2 B 1 0.8 2 B 2 0.7 2 B 3 0.9 3 A 1 0.7 3 A 2 0.9 3 A 3 1.3 4 B 1 0.5 4 B 2 0.6 4 B 3 0.7", header = TRUE) # 示例数据绘图 ggplot(df_demo, aes(x=time, y=lactate, color=group))+ geom_point(stat="summary", fun=mean, size=4)+ geom_line(stat="summary", fun=mean, aes(group=group))+ stat_summary(fun.data=mean_se, geom="errorbar", width=0.01)+ stat_summary( fun = length, geom = "text", aes(label = after_stat(n)), vjust = -1.2, size = 5, show.legend = FALSE )+ xlab("Time point")+ ylab("Lactate (mmol/l)")+ theme_bw()+ theme(text=element_text(family="Helvetica", size=20))
该方案的优势:
- 和原有代码的均值、误差线统计逻辑完全一致,不会出现分组、时间点匹配错位
- 直接调用原始数据绘图,后续增删观测不需要修改标注相关代码
- 仅需调整
vjust/hjust参数即可快速修改标签位置,适配不同出图尺寸
方法2:提前汇总数据标注(适合自定义标签格式)
如果需要自定义标签样式(比如显示为n=3的格式),可以先通过dplyr按分组汇总统计指标,再单独映射文本层,示例代码如下:
library(dplyr) # 提前分组汇总均值、标准误、样本量 df_summary <- df %>% group_by(outcome, time_nrp) %>% summarise( mean_lac = mean(lac, na.rm = TRUE), se_lac = sd(lac, na.rm = TRUE)/sqrt(n()), n = n(), .groups = "drop" ) # 基于汇总后的数据绘图 ggplot(df_summary, aes(x=time_nrp, y=mean_lac, color=as.factor(outcome)))+ geom_point(size=4)+ geom_line(aes(group=as.factor(outcome)))+ geom_errorbar(aes(ymin = mean_lac - se_lac, ymax = mean_lac + se_lac), width=0.01)+ # 自定义标签格式 geom_text(aes(label = paste0("n=", n)), vjust = -1.2, size=5, show.legend = FALSE)+ # 后续坐标轴、主题、颜色设置和原代码完全一致 xlab("NRP Time (hours)")+ ylab("Lactate (mmol/l)")+ theme_bw()+ ggtitle("Panel A")+ theme(plot.title = element_text(hjust=0.5))+ theme(text=element_text(family="Helvetica", size=20))+ scale_color_manual(name="Outcome", breaks=c("0", "1"), labels=c("Negative", "Positive"), values = c("#E12000", "#002F80"))
注意事项
- 如果数据存在缺失值,所有统计函数内记得加
na.rm = TRUE参数,避免计数偏差 - 标签的
size、vjust参数可根据实际出图的尺寸、误差线长度调整,避免和点、误差线、坐标轴元素重叠 - 如果需要将标签放在x轴底部对齐,可将文本层的y映射为固定值(略高于x轴刻度最小值),注意按分组做微小的水平位置偏移,避免同时间点两个分组的标签重叠
内容的提问来源于stack exchange,提问作者Irene
相关产品推荐
相关产品推荐

