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

如何用ggplot2单次填充绘图的两个对立侧区域?

解决ggplot2单次geom_area填充双侧拒绝域的问题

问题原因

geom_area的xlim参数仅支持接收单一连续区间(长度为2的向量),传入多个区间时只会识别第一个区间,因此第二个区间(23,30)被忽略。

解决方案:自定义概率密度函数

通过自定义一个函数,仅在目标拒绝域区间内返回正态分布的密度值,其余区间返回0,这样单次geom_area就能同时填充两个不连续的拒绝区域。

完整代码示例

library(ggplot2)

# 预先计算均值和标准差,提升代码可读性
n <- 30
p <- 0.6
mu <- n * p
sigma <- sqrt(n * p * (1 - p))

# 自定义拒绝域的密度函数:仅在(0,13)和(23,30)返回dnorm值,其余为0
dnorm_reject <- function(x) {
  ifelse((x >= 0 & x <= 13) | (x >= 23 & x <= 30), 
         dnorm(x, mean = mu, sd = sigma), 
         0)
}

# 绘制图形:使用更平滑的x序列保证填充效果
ggplot(data.frame(x = seq(0, 30, length.out = 1000)), aes(x = x)) +
  # 绘制原H0分布曲线
  stat_function(fun = dnorm, 
                args = list(mean = mu, sd = sigma),
                aes(col = "H0")) +
  # 填充拒绝域
  geom_area(stat = "function",
            fun = dnorm_reject,
            aes(fill = "alpha"),
            alpha = 0.3) +
  # 自定义颜色和标签
  scale_color_manual(values = "black", labels = "H₀分布") +
  scale_fill_manual(values = "red", labels = "拒绝域") +
  labs(x = "样本统计量", y = "概率密度", color = "", fill = "") +
  theme_minimal()

关键说明

  1. 自定义函数dnorm_reject通过ifelse判断x是否在拒绝域内,非拒绝域返回0,这样geom_area只会在有效区域填充。
  2. 将x轴数据从0:30改为seq(0,30,length.out=1000),生成更多连续点,避免离散点导致的填充断层。
  3. 添加alpha参数调整填充透明度,让原分布曲线更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:10:40