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

ggplot:填充正态曲线下小区域,消除geom_ribbon的区域连接问题

解决geom_ribbon填充区域时的多余连接问题

哈哈,这个坑我也踩过!你用geom_ribbon时遇到的“两部分连接”问题,本质是因为它会按fill=area自动分组,把所有同组的点都连起来,而且你的代码其实是给整个曲线下方都分了两种颜色填充,而非只保留目标区域的填充。

给你几个更简洁优雅的解决思路:

方法1:用ifelse控制ymax,只填充目标区域

直接在ymax参数里做条件判断,目标区域外的ymax设为0,这样就不会有多余的填充块:

library(tidyverse)

density(rnorm(1000, 0, 1)) %$% 
  data.frame(x=x, y=y) %>% 
  ggplot() +
  geom_line(aes(x, y)) +  # 先画出密度曲线
  geom_ribbon(aes(x = x, ymin = 0, ymax = ifelse(between(x, 1.5, 2.6), y, 0)), 
              fill = "skyblue", alpha = 0.5)

方法2:筛选目标区域后用geom_area填充

这种方法更直观,直接过滤出需要填充的x范围,再用geom_area填充:

library(tidyverse)

density(rnorm(1000, 0, 1)) %$% 
  data.frame(x=x, y=y) %>% 
  ggplot() +
  geom_line(aes(x, y)) +
  geom_area(data = . %>% filter(between(x, 1.5, 2.6)), 
            aes(x, y), fill = "skyblue", alpha = 0.5)

方法3:直接用stat_function,跳过density计算

如果不需要基于模拟数据的密度,直接用正态分布的密度函数更简洁:

library(tidyverse)

ggplot(data.frame(x = seq(-3, 3, 0.01)), aes(x)) +
  stat_function(fun = dnorm, args = list(mean=0, sd=1)) +
  geom_ribbon(aes(ymin = 0, ymax = ifelse(between(x, 1.5, 2.6), dnorm(x), 0)),
              fill = "skyblue", alpha = 0.5)

这几种方法都能避免多余的连接,而且代码比拆分三部分要简洁得多~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:50:57