||

科研绘图不仅要展示真实严谨的数据,更要讲究排版的美观与可读性。
今天小编来分享一个兼具美感和实用性的R包——vbracket,它打破常规,将组间差异的统计学显著性括号直接集成到了图例的垂直结构中,助你的文章插图提升到顶刊发表级的水准。
一、 什么是 vbracket?vbracket 是专门为 ggplot2 开发的一个高度定制化的图例增强包。
它的核心设计理念是:既然图例已经垂直排列了各个分组的名称和颜色,为什么不直接在图例的分组之间拉起垂直括号,来展示它们的两两差异呢?
传统做法 vs vbracket 做法传统做法在绘图区上方拉横向括号。缺点是横向跨度大、挤占 Y 轴高度、多组比较时线条极易交叉。
vbracket 做法在图例文字右侧拉垂直括号(如下图所示)。图面干净,且完美支持多重比较。

(注:图例右侧的垂直括号展示了 WT/Dox vs CH3+5 等组间的显著性差异)
vbracket 高阶美化调整图例line_length:图例中彩色指示线(Legend Line)或色块的物理长度。
line_width:图例彩色指示线或括号线条的粗细。
item_spacing:图例中不同组别(即每一行文字)之间的垂直间距。

vbracket 官方示例效果展示
控制括号与图例标签的水平间距bracket_layer_spacing:可以自由定义紧凑型(Tight Spacing,如 0.04)或宽敞型(Wide Spacing,如 0.12)。这确保了无论有多少层统计 brackets,图例右侧的统计标记都能清晰可读、规整有序,避免了遮挡或过于稀疏导致的视觉松散。

vbracket 官方示例效果展示
二、 实战演练:从安装到出图
下面我们以代谢物数据差异分析为例,展示如何快速上手 vbracket。
第一步:安装包目前该包托管在 GitHub,可以通过 devtools 快速安装:
# 如果未安装 devtools,请先执行 install.packages("devtools")devtools::install_github("h20gg702/vbracket")
第二步:准备数据研究问题:益生菌干预前后,短链脂肪酸(SCFAs)的变化是否不同于安慰剂组?
这里的重点不是简单比较 0d 或 56d 某一个时间点两组有没有差异,而是两组从干预前到干预后的“变化幅度”是否显著不同:
每个受试者先计算:Δ = 56d 相对丰度 - 0d 相对丰度然后比较:Probiotic 组 Δ vs Placebo 组 Δ
第三步:读入短链脂肪酸矩阵和配对元数据suppressPackageStartupMessages({ library(ggplot2) library(vbracket)})metab_file <- file.path(base_dir,"scfa_metabolomics_filtered_by_subject_id_freq_gt1_samples.csv")meta_file <- file.path(base_dir,"filtered_metainfo_subject_id_freq_gt1_rows.csv")metab <- read.csv(metab_file, check.names =FALSE, stringsAsFactors =FALSE)meta <- read.csv(meta_file, check.names =FALSE, stringsAsFactors =FALSE)meta$ghname <- trimws(as.character(meta$ghname))meta$subject_id <- trimws(as.character(meta$subject_id))meta$time_point <- trimws(as.character(meta$time_point))meta$day <- ifelse(meta$time_point =="0d",0, ifelse(meta$time_point =="56d",56,NA_real_))meta$Group <- ifelse(meta$`研究分组` =="安慰剂干预","Placebo", ifelse(meta$`研究分组` =="益生菌干预","Probiotic", as.character(meta$`研究分组`)))meta$Group <- factor(meta$Group, levels = c("Placebo","Probiotic"))sample_cols <- setdiff(colnames(metab),"Metabolite")sample_cols <- sample_cols[sample_cols %in% meta$ghname]long_list <- lapply(seq_len(nrow(metab)),function(i){ data.frame( Metabolite = metab$Metabolite[i], ghname = sample_cols, intensity = as.numeric(metab[i, sample_cols]), stringsAsFactors =FALSE, check.names =FALSE)})long <- do.call(rbind, long_list)plot_df <- merge( long, meta[, c("ghname","subject_id","研究分组","Group","time_point","day")], by ="ghname", all.x =TRUE)
到这里,我们就得到了适合 ggplot2 绘图和统计分析的长格式数据。
第四步:计算“干预前后变化量”并生成显著性标记一部分人的做法是直接在 0d 和 56d 分别比较两组,这样回答的是:
某个时间点,两组是否不同?
但如果你的问题是“干预前后变化是否不同”,更合适的做法是先在每个受试者内部计算变化量:
Δ56d-0d = intensity_56d - intensity_0d
脚本中使用 reshape() 将同一个 subject_id 的 0d 和 56d 拉成一行,然后计算 Δ:
wide <- reshape( sub[, c("Metabolite","subject_id","Group","day","intensity")], idvar = c("Metabolite","subject_id","Group"), timevar ="day", direction ="wide")wide$delta_56d_minus_0d <- wide$intensity.56- wide$intensity.0wide <- wide[!is.na(wide$delta_56d_minus_0d),]
随后,对每个代谢物分别比较两组的变化量:
delta_placebo <- wide$delta_56d_minus_0d[wide$Group =="Placebo"]delta_probiotic <- wide$delta_56d_minus_0d[wide$Group =="Probiotic"]pval <- t.test(delta_placebo, delta_probiotic)$p.value
也就是说,这里的统计检验是:
Placebo 组的 Δ56d-0d vs Probiotic 组的 Δ56d-0d
将 p 值转换成常见的显著性标记:
p_to_star <-function(p){if(is.na(p)) return("NA")if(p <0.001) return("***")if(p <0.01) return("**")if(p <0.05) return("*")"ns"}
最终,每个短链脂肪酸都会得到一个变化量比较结果,例如:
Δ56d-0d: nsΔ56d-0d: *
这个标签不是某个时间点的横向差异,而是干预前后变化幅度的组间差异。
第五步:绘制均值折线图,并用vbracket展示显著性结果绘图部分保持经典的论文风格:
横轴:0d 和 56d
纵轴:Relative Abundance
两条线:Placebo 与 Probiotic
点:组均值
误差线:Mean ± SEM
主题:theme_classic()
显著性:不再堆在图上,而是放进 vbracket 图例里
首先定义颜色:
colors <- c("Placebo"="#00AA00","Probiotic"="#FF4400")groups <- c("Placebo","Probiotic")
然后把变化量检验得到的显著性结果写进 vbracket 的比较结构中:
vb_label <- paste0("Δ56d-0d: ", stat_m$significance)comparisons <- add_bracket_comparisons( groups1 ="Placebo", groups2 ="Probiotic", labels = vb_label)
最后绘图:
p <- ggplot(sum_m, aes(x = day, y = mean, color = Group, group = Group))+ geom_line(linewidth =1.2)+ geom_point(size =3)+ geom_errorbar(aes(ymin = mean - sem, ymax = mean + sem), width =4, linewidth =0.8)+ scale_color_manual(values = colors)+ scale_x_continuous( breaks = c(0,56), limits = c(-3,59), labels = c("0d","56d"))+ labs( title = met, x ="Time point", y ="Relative Abundance")+ theme_classic(base_size =14)+ theme( plot.title = element_text(hjust =0.5, size =16, face ="bold"), legend.position ="none")+ legend_bracket( labels = groups, colors = colors, comparisons = comparisons, position ="topleft", output_width =6, output_height =4, width =0.36, text_size =9, sig_size =8)ggsave(file_png, p, width =6, height =4, dpi =300)

从图中可以直观看出,尽管起点不同,但益生菌干预显著促进了丙酸的产生
三、 贴心避坑指南
为了让大家在排版时少走弯路,在使用 vbracket 时有以下两点需要特别注意:
绝对尺寸对齐
由于图例中文字宽度、括号间距的计算是基于物理绝对单位(如毫米或英寸)进行的,因此在 legend_bracket() 中设置的 output_width 和 output_height,必须与你最终用 ggsave() 保存时的宽高完全一致!否则,导出的 PDF 或 PNG 中括号和文字可能会发生错位。
图例顺序对齐
在编写 legend_bracket(labels = ...) 时,填写的组名顺序要与你在 add_bracket_comparisons() 里使用的组名完全一致,且顺序应符合逻辑(通常是从上到下对应的实验组顺序)。
四、 总结vbracket 包非常适合处理多时间点折线图+显著性标记。如果你也有类似的场景,一起用起来吧!
项目开源地址:https://github.com/h20gg702/vbracket
推荐指数:⭐⭐⭐⭐⭐
本文转自:谷禾健康
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2026-7-15 07:55
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社