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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 19:31:07