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

ggplot2中stat_function与geom_col叠加异常问题求助

问题原因与解决方案

为什么蓝色线条会显示为f(x)=0?

这个问题我之前也碰到过,本质是ggplot的y轴自动适配逻辑在搞鬼:

  • 当你添加geom_col(color = "red")时,ggplot会自动把y轴范围设定为适配数据中quantity列的数值区间。
  • 而你用dgamma计算出的Gamma概率密度值,和quantity的数值量级差得特别大——比如你设置的alpha=1.2、beta=0.01,在x的常见取值范围内,dgamma的结果可能小到1e-6甚至更小,远小于quantity的数值。
  • 这样一来,PDF曲线就被直接压缩到y轴的最底部,看起来就是一条和x轴重合的直线(也就是你看到的f(x)=0)。

实用解决方案

这里给你三种不同场景下的解决方法,你可以根据需求选择:

1. 使用双y轴(推荐,兼顾柱状图和PDF展示)

通过缩放PDF值,让它能和柱状图在同一坐标系下显示,同时添加第二个y轴还原原始PDF数值:

analyzeGamma <- function(csvPath, alpha, beta) {
  dfSamples <- read.csv(file = csvPath, header = TRUE, sep = ",")
  
  # 计算缩放因子:让PDF的最大值匹配quantity的最大值
  x_seq <- seq(min(dfSamples$value), max(dfSamples$value), length.out = 1000)
  pdf_max <- max(dgamma(x_seq, shape = alpha, rate = beta))
  quantity_max <- max(dfSamples$quantity)
  scale_factor <- quantity_max / pdf_max
  
  base <- ggplot(dfSamples, aes(x = value)) +
    geom_col(aes(y = quantity), color = "red") +
    geom_vline(xintercept = qgamma(seq(0.1, 0.9, by = 0.1), alpha, beta)) +
    stat_function(
      fun = function(x) dgamma(x, shape = alpha, rate = beta) * scale_factor,
      colour = "blue"
    ) +
    scale_y_continuous(
      name = "Sample Quantity",
      sec.axis = sec_axis(~ . / scale_factor, name = "Gamma Probability Density")
    )
  return(base)
}

2. 手动设置y轴范围(适合关注分布形状的场景)

如果你的重点是对比柱状图和PDF的分布形状,而非quantity的具体数值,可以手动扩展y轴范围以包含PDF的取值:

analyzeGamma <- function(csvPath, alpha, beta) {
  dfSamples <- read.csv(file = csvPath, header = TRUE, sep = ",")
  
  # 计算PDF的取值范围
  x_range <- range(dfSamples$value)
  pdf_values <- dgamma(seq(x_range[1], x_range[2], length.out = 1000), alpha, beta)
  
  base <- ggplot(dfSamples, aes(x = value, y = quantity)) +
    geom_col(color = "red") +
    geom_vline(xintercept = qgamma(seq(0.1, 0.9, by = 0.1), alpha, beta)) +
    stat_function(
      fun = dgamma, args = list(shape = alpha, rate = beta), colour = "blue"
    ) +
    ylim(0, max(c(dfSamples$quantity, pdf_values)))
  return(base)
}

注意:如果quantity远大于PDF值,柱状图会显得极高,PDF曲线依然很矮,视觉效果可能不够理想。

3. 拆分两个独立图表(最直观,无坐标轴冲突)

把柱状图和PDF曲线分成两个子图,各自使用合适的y轴:

library(gridExtra) # 需要先安装这个包:install.packages("gridExtra")

analyzeGamma <- function(csvPath, alpha, beta) {
  dfSamples <- read.csv(file = csvPath, header = TRUE, sep = ",")
  
  # 柱状图
  p_col <- ggplot(dfSamples, aes(x = value, y = quantity)) +
    geom_col(color = "red") +
    geom_vline(xintercept = qgamma(seq(0.1, 0.9, by = 0.1), alpha, beta)) +
    labs(title = "Sample Quantity Distribution", y = "Quantity")
  
  # PDF曲线
  p_pdf <- ggplot(data.frame(x = seq(min(dfSamples$value), max(dfSamples$value), length.out = 1000)), aes(x = x)) +
    stat_function(fun = dgamma, args = list(shape = alpha, rate = beta), colour = "blue") +
    geom_vline(xintercept = qgamma(seq(0.1, 0.9, by = 0.1), alpha, beta)) +
    labs(title = "Gamma Probability Density Function", y = "Density")
  
  # 排列两个图
  grid.arrange(p_col, p_pdf, ncol = 1)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:29:03