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

geom_density无法正确显示y轴计数,如何自动获取带宽系数?

解决geom_density分组密度图y轴计数异常的自动化方案

问题核心是geom_density默认的after_stat(count)仅为概率密度×样本量,未考虑分组数据自动计算的带宽,导致不同分组的y轴计数无法匹配实际区间计数。要自动化修正,需先获取每个分组的带宽,再用带宽调整y轴数值。

步骤1:预计算每个分组的带宽

用density()函数单独计算每个分组数据的带宽,确保后续绘图时能匹配对应分组的带宽参数。

步骤2:循环生成带修正y轴的密度图

在for循环中,调用预计算的带宽,将after_stat(count)乘以带宽,得到与直方图一致的计数y轴。

完整代码示例

# 加载依赖包
library(ggplot2)
library(ggpubr)

# 构造示例数据(可替换为你的数据集)
set.seed(123)
df <- data.frame(
  group = rep(paste0("group_", 1:4), each = 100),
  value = c(rnorm(100, 0, 1), rnorm(100, 2, 0.5), rnorm(100, 5, 2), rnorm(100, 1, 1.5))
)

# 按分组拆分数据并计算每个分组的带宽
grouped_data <- split(df$value, df$group)
bandwidths <- sapply(grouped_data, function(x) density(x)$bw)

# 循环生成密度图列表
plot_list <- list()
for (g in names(bandwidths)) {
  current_data <- subset(df, group == g)
  current_bw <- bandwidths[g]
  
  p <- ggplot(current_data, aes(x = value)) +
    geom_density(aes(y = after_stat(count) * current_bw), fill = "lightblue", alpha = 0.5) +
    labs(title = g, y = "计数") +
    theme_minimal()
  
  plot_list[[g]] <- p
}

# 合并并输出图形
ggarrange(plotlist = plot_list, ncol = 2, nrow = 2)

批量处理封装函数

如果需要处理多个数据集,可将逻辑封装为函数:

create_count_density_plots <- function(data, group_col, value_col) {
  # 拆分分组并计算带宽
  grouped_data <- split(data[[value_col]], data[[group_col]])
  bandwidths <- sapply(grouped_data, function(x) density(x)$bw)
  
  plot_list <- list()
  for (g in names(bandwidths)) {
    current_data <- subset(data, data[[group_col]] == g)
    current_bw <- bandwidths[g]
    
    p <- ggplot(current_data, aes(x = .data[[value_col]])) +
      geom_density(aes(y = after_stat(count) * current_bw), fill = "lightblue", alpha = 0.5) +
      labs(title = g, y = "计数", x = value_col) +
      theme_minimal()
    
    plot_list[[g]] <- p
  }
  
  return(plot_list)
}

# 调用示例
plot_list <- create_count_density_plots(df, "group", "value")
ggarrange(plotlist = plot_list, ncol = 2, nrow = 2)

验证正确性

可将修正后的密度图与同带宽的直方图叠加,确认线条与直方图顶部对齐:

g <- "group_1"
current_data <- subset(df, group == g)
current_bw <- bandwidths[g]

ggplot(current_data, aes(x = value)) +
  geom_histogram(binwidth = current_bw, fill = "lightgreen", alpha = 0.5) +
  geom_density(aes(y = after_stat(count) * current_bw), color = "red", size = 1) +
  theme_minimal()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:57:43