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

如何在ggplot中叠加不同宽度柱状图:实现城乡收支分位数可视化

解决方案:实现双维度并列叠加柱状图

需求梳理

  • 每个Decile分组下,**收入(income)与支出(expenditures)**柱状图并列展示
  • 农村数据:背景宽柱状图,透明度(alpha)设为0.5
  • 城市数据:前景窄柱状图,叠加在农村柱子上方
  • 收入对应左侧Y轴,支出对应右侧Y轴

问题分析

原代码生成的图表存在以下问题:

  • 收入与支出的柱状图在同一x位置重叠,无法实现并列展示
  • 未区分农村/城市数据的柱子宽度与层级,没有形成背景与前景的叠加效果
  • 双Y轴直接复制左侧刻度,若收入与支出数据范围不同,会导致其中一类数据显示失真
  • fill和alpha的映射未与城乡数据精准绑定,无法实现农村柱半透明的效果

修改后代码

确保数据已加载,且包含Decile(分位数)、Divide(城乡:农村/城市)、Avg.q.hou.inc(收入)、Avg.q.hou.exp(支出)字段:

library(ggplot2)
library(scales)
library(viridis)

# 加载数据(替换为你的数据文件路径)
# data <- read.csv("数据文件路径")

# 生成Viridis配色,对应10个Decile分组
color <- viridis(10)

# 计算收入与支出的比例,用于双Y轴刻度转换(避免数据范围差异导致的显示失真)
inc_range <- range(data$Avg.q.hou.inc, na.rm = TRUE)
exp_range <- range(data$Avg.q.hou.exp, na.rm = TRUE)
scale_factor <- exp_range[2] / inc_range[2]

# 绘制图表
ggplot() +
  # 农村收入:背景宽柱,alpha=0.5
  geom_col(data = subset(data, Divide == "农村"), 
           aes(x = as.numeric(Decile) - 0.2, y = Avg.q.hou.inc, fill = Decile),
           width = 0.35, alpha = 0.5) +
  # 城市收入:前景窄柱,叠加在农村收入柱上方
  geom_col(data = subset(data, Divide == "城市"), 
           aes(x = as.numeric(Decile) - 0.2, y = Avg.q.hou.inc, fill = Decile),
           width = 0.2) +
  # 农村支出:背景宽柱,alpha=0.5(需按比例缩放适配左侧Y轴)
  geom_col(data = subset(data, Divide == "农村"), 
           aes(x = as.numeric(Decile) + 0.2, y = Avg.q.hou.exp / scale_factor, fill = Decile),
           width = 0.35, alpha = 0.5) +
  # 城市支出:前景窄柱,叠加在农村支出柱上方
  geom_col(data = subset(data, Divide == "城市"), 
           aes(x = as.numeric(Decile) + 0.2, y = Avg.q.hou.exp / scale_factor, fill = Decile),
           width = 0.2) +
  # 配置Decile分组配色
  scale_fill_manual(values = color) +
  # 双Y轴设置:左侧为收入,右侧为支出(通过scale_factor还原刻度)
  scale_y_continuous(name = "季度家庭平均收入",
                     labels = comma,
                     sec.axis = sec_axis(~ . * scale_factor,
                                         name = "季度家庭平均支出",
                                         labels = comma)) +
  # 将x轴转换为Decile标签
  scale_x_continuous(breaks = 1:10,
                     labels = paste0("Decile ", 1:10)) +
  # 主题优化
  theme_minimal() +
  theme(legend.position = "bottom",
        axis.title.y.right = element_text(color = "#2c7fb8"),
        axis.title.y.left = element_text(color = "#d95f02"))

代码说明

  1. x轴偏移:将Decile转为数值后,收入柱左移0.2、支出柱右移0.2,实现同一Decile下两类数据的并列效果
  2. 柱子宽度区分:农村柱宽设为0.35,城市柱宽设为0.2,形成背景与前景的层级差异
  3. 双Y轴刻度适配:通过计算收入与支出的最大比例,将支出数据缩放后适配左侧Y轴,右侧轴再反向还原刻度,保证数据显示准确
  4. 图层分层逻辑:先绘制农村背景柱,再叠加城市前景柱,确保层级关系正确
  5. 视觉优化:用Viridis色系区分10个Decile,调整轴标题颜色强化收入/支出的区分度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:47:39