R语言如何用ts.plot为不同尺度ts对象添加双轴实现叠加绘图
R 基于ts.plot实现双坐标轴时间序列绘制
原有代码
library(tseries) library(readxl) data = read_excel(.......) # 构建时间序列对象 equity = ts(data$EQUITY, start = c(2015,01,01), end = c(2020,01,01), frequency = 12) cci = ts(data$CCI, start = c(2015,01,01), end = c(2020,01,01), frequency = 12) # 初始绘制:两个序列尺度差异大,无法叠加 ts.plot(equity, cci, lty = c(1:2))
核心需求
- 保留
ts.plot作为绘图函数,兼容后续tseries对象绘制需求,不使用ggplot2方案 - 新增第二纵坐标轴,解决两序列尺度差异导致的图形分离问题,实现同面板叠加显示
- 支持自定义图例
可直接运行的实现方案
基础R的ts.plot没有内置双轴参数,通过线性尺度映射+手动新增坐标轴的方式即可实现,完全保留ts对象的原生渲染效果,代码如下:
# 1. 预定义尺度映射规则,将CCI的取值范围线性映射到EQUITY的取值区间 eq_val_range <- range(equity, na.rm = TRUE) cci_val_range <- range(cci, na.rm = TRUE) # 正向映射:CCI原始值 -> 适配EQUITY轴的缩放值 map_cci2eq <- function(cci_val) { eq_val_range[1] + (eq_val_range[2] - eq_val_range[1]) * (cci_val - cci_val_range[1]) / (cci_val_range[2] - cci_val_range[1]) } # 反向映射:EQUITY轴刻度值 -> CCI原始值,用于生成第二轴刻度标签 map_eq2cci <- function(eq_val) { cci_val_range[1] + (cci_val_range[2] - cci_val_range[1]) * (eq_val - eq_val_range[1]) / (eq_val_range[2] - eq_val_range[1]) } # 2. 调整画布边距,为右侧第二坐标轴预留空间 par(mar = c(5, 4, 4, 4) + 0.1) # 3. 调用ts.plot绘制第一序列+缩放后的第二序列 ts.plot( equity, map_cci2eq(cci), lty = c(1, 2), col = c("#1f77b4", "#ff7f0e"), ylab = "EQUITY", main = "EQUITY与CCI时序双轴图" ) # 4. 添加右侧第二纵轴 axis( side = 4, at = axTicks(side = 2), labels = round(map_eq2cci(axTicks(side = 2)), 2) ) mtext("CCI", side = 4, line = 2.5) # 5. 添加图例 legend( "topleft", legend = c("EQUITY", "CCI"), lty = c(1, 2), col = c("#1f77b4", "#ff7f0e"), bty = "n" )
方案说明
- 传入
ts.plot的对象始终保持ts类型,时间轴渲染、刻度间隔完全和原生ts.plot效果一致,不存在第三方库的适配问题 - 双轴刻度自动对齐,不需要手动调整刻度位置
- 后续新增更多时间序列时,只需新增对应尺度映射函数、提前预留画布边距即可继续叠加
- 线型、颜色、图例位置、标签均可根据需求自定义调整
内容的提问来源于stack exchange,提问作者Christian Bozzetto
相关产品推荐
相关产品推荐

