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

如何在ggplot中绘制双轴图并匹配刻度实现图层叠加?

搞定ggplot双Y轴刻度匹配问题

问题背景

要做一个双Y轴图表,但production(产量,数值在10000-10500之间)和price(价格,数值98-110)的刻度差太大,直接叠图层的话,其中一个会显示得完全不正常。核心是要让右侧Y轴的刻度和左侧对应,让两个图层能准确对齐展示。

示例数据

df <- data.frame(year= c(2000, 2001, 2002, 2003, 2004, 2005),
                 price= c(100, 105, 102, 110, 98, 102),
                 production= c(10000, 10500, 10250, 10300, 10450, 10320))

现有代码的问题

你现在写的代码把左侧Y轴范围设成了价格的区间,导致产量柱子被压得几乎看不见,右侧轴也没做任何有效转换,完全起不到双Y轴的作用:

ggplot() + 
  geom_bar(data= df, aes(x=year, y=production), stat = "identity") +
  geom_line(data= df, aes(x=year, y=price), color= "red") +
  labs(x="Year", y = "Production (Kg)") +
  scale_y_continuous(limits=c(95, 110), 
    sec.axis = sec_axis(~ . *1 , name = "Price ($)")) +
  theme_bw()

正确的实现方法

ggplot的双Y轴本质是把其中一组数据按比例转换到另一组的刻度区间,然后右侧轴再用反向公式还原原始刻度。具体步骤如下:

  1. 先算出两组数据的极值:产量的最小/最大值、价格的最小/最大值;
  2. 把价格数据转换到产量的刻度区间里,这样折线图就能和柱状图的高度匹配;
  3. 给右侧Y轴设置反向转换公式,让它显示原始的价格数值。

直接用下面的代码就行:

library(ggplot2)

# 计算两组数据的极值,用来做转换
prod_min <- min(df$production)
prod_max <- max(df$production)
price_min <- min(df$price)
price_max <- max(df$price)

ggplot(df, aes(x = year)) +
  # 产量柱状图,用原始数据
  geom_bar(aes(y = production), stat = "identity", fill = "steelblue", alpha = 0.7) +
  # 价格折线图:把价格转成产量区间的数值,这样能和柱子对齐
  geom_line(aes(y = (price - price_min)/(price_max - price_min)*(prod_max - prod_min) + prod_min), 
            color = "red", linewidth = 1) +
  # 设置双Y轴:左侧是产量,右侧通过反向公式还原价格
  scale_y_continuous(
    name = "Production (Kg)",
    sec.axis = sec_axis(
      trans = ~ (. - prod_min)/(prod_max - prod_min)*(price_max - price_min) + price_min,
      name = "Price ($)"
    )
  ) +
  labs(x = "Year") +
  theme_bw()

效果说明

这样改完之后,折线图的位置会和柱状图的刻度范围完全匹配,右侧Y轴显示的是真实的价格数值,两个图层都能正常展示,不会出现其中一个被压缩的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:55:54