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

解决ggplot2绘制垂直双直方图报错并添加正态分布概率曲线

垂直双直方图加正态分布曲线的实现方案

错误原因

geom_histogram()依赖的stat_bin()仅允许指定x或y其中一个美学映射,你同时设置了x = val和y = met,导致统计计算冲突,触发报错。

常规垂直分面实现

以下代码实现垂直排列的两个直方图,并为每个分组添加对应均值和标准差的正态分布曲线:

library(ggplot2)
set.seed(1)
# 修正原数据的类别命名笔误,确保分组清晰
dat <- rbind(
  data.frame(val = rnorm(100), met = "Metric1"),
  data.frame(val = rt(100, 2), met = "Metric2")
)

ggplot(dat, aes(x = val, fill = met, color = met)) +
  # 绘制密度直方图,与正态曲线刻度对齐
  geom_histogram(aes(y = ..density..), bins = 15, alpha = 0.5, position = "identity") +
  # 添加对应分组的正态分布曲线
  stat_function(
    fun = dnorm,
    args = function(group) list(mean = mean(group$val), sd = sd(group$val)),
    aes(color = met),
    linewidth = 1
  ) +
  # 垂直分面,单列排列子图
  facet_wrap(~met, ncol = 1) +
  # 移除冗余图例
  theme(legend.position = "none")

镜像式垂直排列(贴近示例效果)

如果需要实现类似示例的上下镜像效果,可对其中一组的密度值取反:

library(ggplot2)
set.seed(1)
dat <- rbind(
  data.frame(val = rnorm(100), met = "Metric1"),
  data.frame(val = rt(100, 2), met = "Metric2")
)
# 添加密度方向标识,用于镜像
dat$density_dir <- ifelse(dat$met == "Metric1", 1, -1)

ggplot(dat, aes(x = val, fill = met, color = met)) +
  # 绘制镜像直方图
  geom_histogram(aes(y = ..density.. * density_dir), bins = 15, alpha = 0.5, position = "identity") +
  # 为Metric1添加正向正态曲线
  stat_function(
    data = subset(dat, met == "Metric1"),
    fun = function(x) dnorm(x, mean = mean(subset(dat, met == "Metric1")$val), sd = sd(subset(dat, met == "Metric1")$val)),
    linewidth = 1, color = "#F8766D"
  ) +
  # 为Metric2添加反向正态曲线
  stat_function(
    data = subset(dat, met == "Metric2"),
    fun = function(x) -dnorm(x, mean = mean(subset(dat, met == "Metric2")$val), sd = sd(subset(dat, met == "Metric2")$val)),
    linewidth = 1, color = "#00BFC4"
  ) +
  # 隐藏y轴正负标签,仅显示绝对值
  scale_y_continuous(labels = abs) +
  theme(legend.position = "top")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:35:13