如何用stat_density_ridges为不同组设置截断点并着色p值区域?
使用stat_density_ridges绘制带p值区域标记的Bootstrap零分布
完全可以用stat_density_ridges(或geom_density_ridges)实现需求。核心思路是先计算每个分组的密度分布数据,筛选出真实统计量(sc)截断点后的区域进行颜色填充,再叠加统计量标记线与数值标注。
步骤1:构造示例数据
先模拟符合需求的数据集,包含分组列label、Bootstrap零分布列null、真实统计量列sc:
library(tidyverse) library(ggridges) set.seed(123) df <- bind_rows( tibble(label = "Group A", null = rnorm(1000, mean = 0, sd = 1), sc = 1.8), tibble(label = "Group B", null = rnorm(1000, mean = 0, sd = 1.2), sc = 2.2), tibble(label = "Group C", null = rnorm(1000, mean = 0, sd = 0.8), sc = 1.5) ) %>% group_by(label) %>% mutate(sc = first(sc)) %>% ungroup()
步骤2:预处理密度数据
计算每个分组的密度分布,提取用于填充p值区域的子集:
# 计算每个分组的密度曲线数据 density_data <- df %>% group_by(label) %>% group_modify(~ { dens <- density(.x$null, adjust = 1.5) tibble(x = dens$x, y = dens$y, sc = .x$sc[1]) }) %>% ungroup() # 筛选出真实统计量右侧的区域数据(用于填充颜色) fill_data <- density_data %>% filter(x >= sc)
步骤3:绘制最终图形
叠加基础脊线、p值填充区域、统计量标记线与标注:
ggplot() + # 绘制基础Bootstrap零分布脊线 geom_density_ridges( data = df, aes(x = null, y = label), fill = "lightgray", color = "black", alpha = 0.6, scale = 0.9 ) + # 填充统计量右侧的p值区域 geom_ribbon( data = fill_data, aes( x = x, ymin = as.numeric(factor(label)) - 0.45, ymax = as.numeric(factor(label)) + 0.45, group = label ), fill = "#ff6b6b", alpha = 0.7 ) + # 添加真实统计量的虚线标记 geom_vline( data = df %>% distinct(label, sc), aes(xintercept = sc, color = label), linetype = "dashed", linewidth = 1 ) + # 标注真实统计量数值 geom_text( data = df %>% distinct(label, sc), aes(x = sc, y = label, label = paste("sc =", round(sc, 2))), hjust = -0.1, color = "darkred", size = 4 ) + # 主题与标签调整 theme_ridges() + labs( x = "Bootstrap Null Distribution", y = "Group", title = "Bootstrap Null Distributions with Statistic Markers" ) + theme( legend.position = "none", plot.title = element_text(hjust = 0.5, size = 14) )
关键细节说明
- 密度平滑度:通过
density()的adjust参数调整曲线平滑程度,适配你的数据分布。 - 填充区域对齐:将
label转为数值,配合ymin/ymax参数让填充区域精准贴合脊线高度。 - 颜色与透明度:可根据需求替换填充色、调整
alpha参数控制视觉层次。
内容的提问来源于stack exchange,提问作者TanZor
相关产品推荐
相关产品推荐

