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
相关产品推荐
相关产品推荐

