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

如何在ggplot2的geom_density中按关键值设置不同填充颜色

如何在ggplot2的geom_density中按关键值设置不同填充颜色

嗨,我完全懂你遇到的困扰——用geom_histogram能轻松按临界值给不同区间上色,但换成geom_density要么变成两条分开的曲线,要么加了group=1后填充直接失效,对吧?咱们来一步步解决这个问题!

首先得搞清楚问题出在哪:当你把fill映射到treat_b > CRIT[[2]] | treat_b < CRIT[[1]]这个逻辑变量时,ggplot默认会把这个变量当成分组依据,所以直接生成了两条独立的密度曲线(一条对应“显著”的数值,一条对应“不显著”的),这可不是你想要的单条曲线分区填充效果。而加group=1虽然能强制把所有数据归为一组,但又会让填充的逻辑映射彻底失效,自然看不到分区上色了。

下面给你两种可行的解决方案:


方法一:用stat_density结合after_stat()直接在ggplot中处理

这种方法不用额外预处理数据,直接在图层里用after_stat()访问密度计算后的x值,判断是否在临界区间外,然后实现分区填充:

library(tidyverse)

set.seed(42)

P <- .65
K <- 1e3
SIMS <- 4e3

df <-
  tibble(
    recipe_a = rbinom(SIMS, K, P) / K,
    recipe_b = rbinom(SIMS, K, P) / K,
    treat_a = recipe_a-recipe_b,
    treat_b = recipe_b-recipe_a
  )

CRIT <- quantile(df$treat_b, c(.025, .975))

# 核心代码
df |>
  ggplot(aes(x = treat_b)) +
  stat_density(
    aes(fill = after_stat(x < CRIT[[1]] | x > CRIT[[2]])),
    geom = "area",  # 用area geom来生成填充区域
    alpha = 0.7,    # 调整透明度让颜色更柔和
    bins = 50
  ) +
  labs(fill = "Stat Sig")

这里的关键是after_stat(x)——它能让我们访问到stat_density计算出来的密度曲线的x坐标值,这样就能针对每个x点判断是否落在临界区间外,进而给对应区域填充不同颜色,同时保证是单条密度曲线的分区效果。


方法二:先手动计算密度数据,再用geom_area填充

如果你想更灵活地控制密度数据(比如查看中间计算结果),可以先手动算出密度数据,再用geom_area实现分区填充:

# 第一步:计算treat_b的密度数据并整理成数据框
density_data <- df |>
  pull(treat_b) |>
  density(n = 512) |>  # n控制密度曲线的平滑度,数值越高越平滑
  as_tibble() |>
  mutate(
    stat_sig = x < CRIT[[1]] | x > CRIT[[2]]  # 添加判断是否显著的列
  )

# 第二步:用geom_area画图
density_data |>
  ggplot(aes(x = x, y = density, fill = stat_sig)) +
  geom_area(alpha = 0.7) +
  labs(x = "treat_b", fill = "Stat Sig")

这种方法的好处是你可以清晰看到密度计算的中间数据,方便后续调整或添加其他自定义逻辑。

两种方法都能实现你想要的“单条密度曲线按临界值分区填充”的效果,选哪种看你的需求就好~

备注:内容来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 10:33:05