如何用ggplot和ggpubr为水平森林图添加外部计算的P值?
解决水平森林图添加P值时的
Discrete value supplied to continuous scale错误 问题重现
你尝试绘制展示比值比(Odds Ratio)的水平森林图,使用ggpubr::stat_pvalue_manual添加P值时触发以下错误:
Error: Discrete value supplied to continuous scale
数据集
order<-data.frame( Order=factor(c(1:6),levels=c(6:1)), OR=c(1,0.92,0.84,0.83,0.81,0.82), CI_low=c(NA,0.87,0.79,0.77,0.74,0.74), CI_high=c(NA,0.99,0.90,0.89,0.88,0.90), p_between=c(NA,0.01550,0.00610,0.72685,0.61190,0.86702), p_between_sig=c(NA,"*","**","NS","NS","NS"), p_overall=1.662490e-09, p_overall_sig=c("****") ) stat.test<-data.frame( group1=c(1,2,3,4,5,1), group2=c(2,3,4,5,6,6), p=c(0.02,0.01,0.73,0.61,0.87,1.6e-09), p.signif=c("*","**","NS","NS","NS","****"))
初始森林图代码
library(ggplot2) library(ggpubr) fp <- order %>% ggplot(aes(y=Order, x=OR, label=Order)) + geom_point(size=4, shape=15) + theme_classic()+ geom_errorbarh(aes(xmin=CI_low, xmax=CI_high), height=0)+ geom_vline(xintercept=1, linetype='longdash') + coord_cartesian(xlim=c(.7, 1.25),ylim=c(1,7))+ labs(x="Odds Ratio",y="Order")+ annotate("text", x = .85, y = 7, label = "Lower Detection") + annotate("text", x = 1.1, y = 7, label = "Higher Detection") fp
报错的P值添加代码
fp + stat_pvalue_manual(stat.test, label = "p.signif", tip.length=0.01, y.position = c(1.05,1.05,1.05,1.05,1.05,1.1), coord.flip=T)
错误原因
coord.flip=T参数冲突:你的初始图已经通过geom_errorbarh实现水平布局,y轴是离散因子(Order),x轴是连续数值(OR)。stat_pvalue_manual的coord.flip=T会强制翻转坐标轴,导致离散值被传入连续刻度,触发错误。- 分组不匹配:
stat.test中的group1/group2是数值,而order$Order是因子,两者层级对应关系未对齐。 y.position设置错误:原y.position数值对应错误,未匹配Order因子的实际位置(因子Order=6对应y=1,Order=1对应y=6)。
修复方案
步骤1:修正stat.test的分组
将group1和group2转换为与order$Order一致的因子,确保分组匹配:
stat.test <- stat.test %>% mutate( group1 = factor(group1, levels = c(6:1)), group2 = factor(group2, levels = c(6:1)) )
步骤2:调整stat_pvalue_manual参数
- 移除
coord.flip=T参数 - 修正
y.position为对应因子的位置 - 自定义
label参数实现带括号的P值格式
完整修复代码
library(ggplot2) library(ggpubr) library(dplyr) # 修正stat.test的分组 stat.test <- stat.test %>% mutate( group1 = factor(group1, levels = c(6:1)), group2 = factor(group2, levels = c(6:1)) ) # 绘制森林图并添加带括号的P值 fp <- order %>% ggplot(aes(y=Order, x=OR, label=Order)) + geom_point(size=4, shape=15) + theme_classic()+ geom_errorbarh(aes(xmin=CI_low, xmax=CI_high), height=0)+ geom_vline(xintercept=1, linetype='longdash') + coord_cartesian(xlim=c(.7, 1.3),ylim=c(1,7))+ labs(x="Odds Ratio",y="Order")+ annotate("text", x = .85, y = 7, label = "Lower Detection") + annotate("text", x = 1.1, y = 7, label = "Higher Detection") + # 添加带括号的P值 stat_pvalue_manual( stat.test, label = "p = {round(p, 3)} ({p.signif})", # 自定义带括号的P值格式 tip.length = 0.01, y.position = c(1.2, 2.2, 3.2, 4.2, 5.2, 6.5), # 对应每个对比的y位置 x.position = 1.18 # 设置P值的x位置 ) fp
效果说明
- 修正后的代码会在每个森林图条目的右侧添加带括号的P值和显著性标记
- 整体对比的P值会显示在最上方的位置
- 完全避免了坐标轴翻转带来的离散/连续刻度冲突问题
内容的提问来源于stack exchange,提问作者Hong
相关产品推荐
相关产品推荐

