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

