使用ggplot绘制含左侧双线条与右侧次坐标轴的折线图
解决ggplot左侧双折线+右侧次坐标轴的问题
核心思路
ggplot本身不原生支持多组独立y轴,次坐标轴的实现依赖于数值缩放映射:将右侧系列的数值按比例缩放到左侧坐标轴的范围,绘图后再通过次坐标轴反转缩放,还原真实数值。
完整代码实现
library(ggplot2) # 示例数据(你的原始数据) years <- rep(c("2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022"), 3) legend <- c(rep("price1", 11), rep("price2", 11), rep("price3", 11)) numbers <- c(8,3,14,10,16,19,26,23,9,3,16,2.0,0.6,3.0,2.1,3.3,4.1,6.1,6.0,3.4,1.4,5.6, 3943200,4694600,4644400,4876700,4792600,4610700,4239000,3832300, 2647500,2179400,2853700) dataset <- data.frame(years, legend, numbers) # 计算缩放因子:将price3的数值范围映射到price1的范围 scale_factor <- max(dataset$numbers[dataset$legend == "price3"]) / max(dataset$numbers[dataset$legend == "price1"]) # 绘制图形 ggplot() + # 左侧第一条折线:price1 geom_line(data = subset(dataset, legend == "price1"), aes(x = years, y = numbers, color = "price1"), group = 1, linewidth = 1) + # 左侧第二条折线:price2 geom_line(data = subset(dataset, legend == "price2"), aes(x = years, y = numbers, color = "price2"), group = 1, linewidth = 1) + # 右侧折线:price3(先缩放数值匹配左侧轴) geom_line(data = subset(dataset, legend == "price3"), aes(x = years, y = numbers / scale_factor, color = "price3"), group = 1, linewidth = 1) + # 左侧坐标轴标签 ylab("Price 1 & Price 2") + # 设置右侧次坐标轴,反转缩放还原真实数值 scale_y_continuous(sec.axis = sec_axis(~ . * scale_factor, name = "Price 3")) + # 自定义折线颜色 scale_color_manual(values = c("price1" = "#E63946", "price2" = "#457B9D", "price3" = "#1D3557")) + # 图例标题 labs(color = "指标") + # 美化主题 theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1))
关键说明
- 分组参数
group=1:因为years是字符型变量,ggplot无法自动识别为连续时间序列,必须指定group=1才能将各年份的点连成折线。 - 缩放因子的选择:这里用price1的最大值作为基准,你也可以根据需求换成price2的最大值,或两者的均值,只要保证缩放后右侧折线在图中的比例合理即可。
- 次坐标轴逻辑:
sec_axis(~ . * scale_factor)表示将左侧轴的数值乘以缩放因子,还原price3的真实数值,从而在右侧显示正确刻度。
内容的提问来源于stack exchange,提问作者USER12345
相关产品推荐
相关产品推荐

