如何在ggplot2中为箱线图加权重?直方图权重失效及加权均值问题
ggplot2加权可视化问题解决方案
一、直方图权重不生效的原因及修正
权重未直观体现的核心原因是代码中使用了y = ..density..——密度直方图会自动归一化至总面积为1,加权与不加权的视觉差异被抵消。换成计数轴(y = ..count..)即可直观看到权重的影响。
修正后的加权直方图代码
library(ggplot2) # 加权直方图(计数y轴) ggplot(data = datos_ComValenciana, aes(x = ingnorm, weight = factorel)) + geom_histogram(fill="#5DC863FF", alpha=0.6, col="black", bins=18) + xlab("归一化收入") + ylab("加权计数") + ggtitle("带样本权重的收入直方图") # 对比:无权重直方图 ggplot(data = datos_ComValenciana, aes(x = ingnorm)) + geom_histogram(fill="#440154FF", alpha=0.6, col="black", bins=18) + xlab("归一化收入") + ylab("原始计数") + ggtitle("无权重的收入直方图")
若仍需展示密度,可保留y = ..density..,此时权重已参与计算,仅因归一化导致视觉相似,可通过提取图层数据验证加权效果。
二、在直方图中添加加权均值
先计算收入的加权均值,再通过垂直线和文本标注添加到图中:
# 计算加权均值 weighted_mean <- weighted.mean(datos_ComValenciana$ingnorm, w = datos_ComValenciana$factorel) ggplot(data = datos_ComValenciana, aes(x = ingnorm, weight = factorel)) + geom_histogram(fill="#5DC863FF", alpha=0.6, col="black", bins=18) + # 添加加权均值垂直线 geom_vline(xintercept = weighted_mean, color = "red", linetype = "dashed", linewidth = 1) + # 添加均值文本标注 geom_text(aes(x = weighted_mean, y = max(..count..)*0.9, label = paste("加权均值:", round(weighted_mean, 2))), stat = "bin", bins=18, color = "red", fontface = "bold") + xlab("归一化收入") + ylab("加权计数") + ggtitle("带加权均值的收入直方图")
三、绘制加权箱线图
ggplot2原生geom_boxplot不支持直接传入权重,可通过以下两种方式实现:
方法1:使用ggpol包的geom_boxploth
该函数原生支持weight参数,实现简单:
# 安装并加载ggpol if (!require(ggpol)) install.packages("ggpol") library(ggpol) ggplot(datos_ComValenciana, aes(x = "", y = ingnorm, weight = factorel)) + geom_boxploth(fill="#21908CFF", alpha=0.6) + xlab("") + ylab("归一化收入") + ggtitle("带样本权重的收入箱线图")
方法2:手动计算加权分位数后绘制
使用Hmisc包计算加权四分位数,再手动构造箱线图数据:
if (!require(Hmisc)) install.packages("Hmisc") library(Hmisc) library(dplyr) # 计算加权分位数 weighted_stats <- datos_ComValenciana %>% summarize( min = wtd.quantile(ingnorm, weights = factorel, probs = 0), q1 = wtd.quantile(ingnorm, weights = factorel, probs = 0.25), median = wtd.quantile(ingnorm, weights = factorel, probs = 0.5), q3 = wtd.quantile(ingnorm, weights = factorel, probs = 0.75), max = wtd.quantile(ingnorm, weights = factorel, probs = 1) ) # 转换为箱线图所需格式 boxplot_data <- data.frame( x = factor(""), ymin = weighted_stats$min, lower = weighted_stats$q1, middle = weighted_stats$median, upper = weighted_stats$q3, ymax = weighted_stats$max ) # 绘制加权箱线图 ggplot(boxplot_data, aes(x = x)) + geom_boxplot(aes(ymin = ymin, lower = lower, middle = middle, upper = upper, ymax = ymax), stat = "identity", fill="#21908CFF", alpha=0.6) + xlab("") + ylab("归一化收入") + ggtitle("手动计算分位数的加权箱线图")
内容的提问来源于stack exchange,提问作者Beatriz
相关产品推荐
相关产品推荐

