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

Matplotlib X轴与次级Y轴自定义配置问题求助

解决Matplotlib绘图的两个自定义需求问题

数据处理代码(可跳过)

# 导入库
import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

# 常量定义
start_date = "2018-01-01"
end_date = "2023-01-01"

# 获取数据
tenYear_master = yf.download('^TNX', start_date, end_date)
thirtyYear_master = yf.download('^TYX', start_date, end_date)

# 只保留调整后收盘价列
tenYear = tenYear_master['Adj Close'].to_frame()
thirtyYear = thirtyYear_master['Adj Close'].to_frame()

# 重命名列
tenYear.rename(columns={'Adj Close': 'Adj Close - Ten Year'}, inplace=True)
thirtyYear.rename(columns={'Adj Close': 'Adj Close - Thirty Year'}, inplace=True)

# 合并数据框
data = tenYear.join(thirtyYear)

# 添加利差列(30年期收益率 - 10年期收益率)
data['Spread'] = data['Adj Close - Thirty Year'] - data['Adj Close - Ten Year']

data

绘图代码(运行正常)

'''绘制数据'''
# 移除图表的顶部、左侧和右侧边框
plt.rcParams['axes.spines.top'] = False
plt.rcParams['axes.spines.left'] = False
plt.rcParams['axes.spines.right'] = False
fig, ax = plt.subplots(figsize=(15,10))
data.plot(ax=ax, secondary_y=['Spread'], ylabel='Yield', legend=False);

'''将左侧Y轴刻度改为百分比格式'''
left_yticks = ax.get_yticks().tolist()
ax.yaxis.set_major_locator(mticker.FixedLocator(left_yticks))
ax.set_yticklabels(("%.1f" % tick + '%') for tick in left_yticks);

# 添加图例
fig.legend(loc="upper center", ncol=3, frameon=False)
fig.tight_layout()
plt.show()

待解决的自定义需求

  • 当前X轴仅每年显示一个刻度与标签,需修改为每3个月显示一个,格式为MMM-YY(示例:Jan-18);
  • 右侧Y轴对应Spread数据(计算方式为30年期收益率-10年期收益率),需仅翻转刻度标签的符号(原范围-0.20.8改为0.2-0.8),不修改原始数据与曲线。

尝试的错误代码(右侧Y轴显示不完整)

'''修改右侧Y轴刻度标签'''
right_yticks = (ax.right_ax).get_yticks().tolist()
# 遍历并将每个右侧Y轴刻度标签乘以-1
for index, value in enumerate(right_yticks):
  right_yticks[index] = value*(-1)
(ax.right_ax).yaxis.set_major_locator(mticker.FixedLocator(right_yticks))
(ax.right_ax).set_yticklabels(right_yticks)

正确解决方案

1. 调整X轴刻度与格式

用matplotlib.dates模块的MonthLocator设置每3个月一个刻度,再用DateFormatter指定%b-%y格式(对应MMM-YY)。

2. 修复右侧Y轴刻度翻转问题

不需要修改刻度的位置,只在设置标签时对原始刻度值取反,保持刻度位置不变,避免破坏数据映射导致显示异常。

整合后的完整绘图代码:

'''绘制数据'''
# 移除图表的顶部、左侧和右侧边框
plt.rcParams['axes.spines.top'] = False
plt.rcParams['axes.spines.left'] = False
plt.rcParams['axes.spines.right'] = False
fig, ax = plt.subplots(figsize=(15,10))
data.plot(ax=ax, secondary_y=['Spread'], ylabel='Yield', legend=False);

'''将左侧Y轴刻度改为百分比格式'''
left_yticks = ax.get_yticks().tolist()
ax.yaxis.set_major_locator(mticker.FixedLocator(left_yticks))
ax.set_yticklabels(("%.1f" % tick + '%') for tick in left_yticks);

'''调整X轴刻度:每3个月一个,格式为MMM-YY'''
import matplotlib.dates as mdates
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=3))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))

'''翻转右侧Y轴刻度标签符号(不修改数据)'''
right_ax = ax.right_ax
# 获取原始刻度位置
right_tick_positions = right_ax.get_yticks()
# 对刻度值取反作为标签
right_ax.set_yticklabels([f"{-tick:.1f}" for tick in right_tick_positions])

# 添加图例
fig.legend(loc="upper center", ncol=3, frameon=False)
fig.tight_layout()
plt.show()

代码说明

  • X轴部分:MonthLocator(interval=3)设置每3个月生成一个刻度,DateFormatter('%b-%y')将日期格式化为缩写月份+两位年份;
  • 右侧Y轴部分:保留原始刻度位置不变,仅在生成标签时对每个刻度值取反,曲线位置不受影响,仅标签符号翻转,完全匹配需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:55:21