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

如何在同一张图中绘制双Y轴:搭配geom_col与geom_line图层

问题描述

我有如下R语言数据集:

yeardesc<-seq(2002,2020,2)

prop1<-c(0.6751152,0.6746591,0.6913932,0.74829,0.7085363,0.7679045,0.8328877,0.7802125,0.7992271,0.8180833)
prop2<-c(0.02150538,0.07438795,0.05994291,0.08120438,0.09961588,0.07418163,0.07314629,0.1220751,0.1073002,0.1470971)
money1<-c(3783.255,4512.181,4237.779,4163.842,4267.878,4708.089,4244.439,4407.01,4193.522,5140.635)
money2<-c(382.9129,643.6798,606.3505,600.3303,713.0684,405.1913,463.76,787.4756,572.8035,1010.126)

data<-data.frame(yeardesc,prop1,prop2,money1,money2)

我需要绘制满足以下要求的可视化图形:

  • 用蓝色线条(geom_line)展示prop1和prop2的趋势
  • 用红色柱状(geom_col)展示money1和money2的数值
  • 配置两个刻度范围不同的Y轴,分别对应比例数据和金额数据
解决方案

在ggplot2中实现双Y轴,核心思路是通过数据缩放让两组不同量级的数据适配同一坐标系,再通过手动设置右侧轴的刻度标签还原原始数值。以下是可直接运行的完整代码:

library(ggplot2)

# 计算金额数据的缩放比例,使其最大值匹配比例数据的最大值
scale_ratio <- max(data[, c("prop1", "prop2")]) / max(data[, c("money1", "money2")])

ggplot(data, aes(x = yeardesc)) +
  # 绘制红色柱状图:先画money1(宽柱),再画money2(窄柱),注意缩放数据
  geom_col(aes(y = money1 * scale_ratio), fill = "red", alpha = 0.7, width = 0.8) +
  geom_col(aes(y = money2 * scale_ratio), fill = "darkred", alpha = 0.7, width = 0.4) +
  # 绘制蓝色线条:prop1(实线)、prop2(虚线)
  geom_line(aes(y = prop1), color = "blue", linewidth = 1.2) +
  geom_line(aes(y = prop2), color = "darkblue", linewidth = 1.2, linetype = "dashed") +
  # 给线条添加点标记,提升可读性
  geom_point(aes(y = prop1), color = "blue", size = 2) +
  geom_point(aes(y = prop2), color = "darkblue", size = 2) +
  # 配置双Y轴:左侧为比例数据,右侧为还原后的金额数据
  scale_y_continuous(
    name = "比例值",
    limits = c(0, max(data[, c("prop1", "prop2")]) * 1.1),
    breaks = seq(0, 0.9, 0.1),
    sec.axis = sec_axis(
      ~ . / scale_ratio,
      name = "金额值",
      breaks = seq(0, 6000, 1000)
    )
  ) +
  # 配置X轴刻度为指定年份
  scale_x_continuous(name = "年份", breaks = yeardesc) +
  # 主题与样式调整
  theme_minimal() +
  theme(
    axis.title.y = element_text(color = "blue"),
    axis.title.y.right = element_text(color = "red"),
    legend.position = "top",
    plot.title = element_text(hjust = 0.5)
  ) +
  # 添加标题与图例
  labs(
    title = "年份-比例与金额趋势对比",
    color = "指标",
    fill = "金额指标"
  ) +
  # 统一图例(可选,让线条和柱子的图例合并)
  scale_color_manual(values = c("blue", "darkblue"), labels = c("prop1", "prop2")) +
  scale_fill_manual(values = c("red", "darkred"), labels = c("money1", "money2"))

关键说明:

  • 数据缩放:scale_ratio将金额数据按比例缩小,使其范围与比例数据对齐,避免柱子过高遮挡线条。
  • 图层顺序:先绘制柱状图,再绘制线条,确保线条显示在上方。
  • 双Y轴实现:sec.axis参数通过反向运算(~ . / scale_ratio)将缩放后的数值还原为原始金额,实现右侧轴的刻度匹配。
  • 样式优化:用颜色区分两组数据,添加透明度、点标记和主题调整,提升图形的可读性与美观度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:24:54