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
相关产品推荐
相关产品推荐

