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

ggplot2 geom_area添加标签:标准正态分布区间占比标注问题

R ggplot标准正态分布面积图添加区间占比标签解决方案

以下是完整可运行的修改后代码,可直接实现给每个面积区块添加对应区间占比标签的效果:

library(tidyverse)
library(ggplot2)
library(magrittr)

sim_dat = data.frame(z = seq(-5,5, length.out = 1001))
sim_dat$y = dnorm(sim_dat$z, mean = 0, sd=1)

# 填写z-score分位点,0会默认自动加入无需填写
zscores <- c(-1,1.5)
zscores <- sort( setdiff(zscores,0) )
bkpoints <- sort( c(-Inf, zscores,0, Inf))

# 计算各区间数据占比+标签坐标
pctdata <- numeric(length=length(bkpoints)-1)
interval <- character(length=length(bkpoints)-1)
x_mid <- numeric(length=length(bkpoints)-1) # 标签x轴定位:区间中点
y_pos <- numeric(length=length(bkpoints)-1) # 标签y轴定位:色块中心高度

for(i in 1:length(pctdata)){
  pctdata[i] <- plyr::round_any(  pnorm(q=bkpoints[i+1]) - pnorm(q=bkpoints[i]) , 0.0001)
  interval[i] <- paste0(bkpoints[i],",",bkpoints[i+1])
  # 处理无穷边界的中点取值
  left <- bkpoints[i]
  right <- bkpoints[i+1]
  x_mid[i] <- case_when(
    left == -Inf ~ -4.5,
    right == Inf ~ 4.5,
    TRUE ~ (left + right)/2
  )
  # 标签y高度取区间中点对应密度的1/2,刚好落在色块中心
  y_pos[i] <- dnorm(x_mid[i])/2
}

pctdata_df <- cbind.data.frame(interval,pctdata,x_mid,y_pos,stringsAsFactors=FALSE)

sim_dat$standard_normal_sections = cut(sim_dat$z, breaks = bkpoints)

p1 <- ggplot2::ggplot(sim_dat, aes(z, y, fill = standard_normal_sections)) + 
  geom_area(alpha = 0.7) + # 加透明度避免遮挡标签
  # 新增标签层,关闭全局映射继承避免报错
  geom_text(data = pctdata_df, aes(x = x_mid, y = y_pos, 
                                   label = scales::percent(pctdata, accuracy = 0.01)),
            inherit.aes = F, size = 4, fontface = "bold") +
  scale_x_continuous(breaks= c(seq(-5,5,1), zscores)) +
  labs(x = "Z-score", y = "概率密度", fill = "Z区间") +
  theme_bw()

p1

pctdata_df

适配说明

  • 支持任意自定义z分位点输入,程序会自动计算所有区间的标签位置
  • 占比自动转为百分比格式,更适配本科统计教学的展示需求
  • 可自行调整geom_text的size、color参数修改标签样式

内容的提问来源于stack exchange,提问作者Ralph Asher

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 19:57:03