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

Matplotlib衰退区间着色后无法缩放问题的解决方案咨询

解决衰退区间着色与图表缩放兼容问题

问题描述

我有一个0/1类型的RECESSION变量,0代表无衰退、1代表衰退,希望用axvspan或fill类方法为衰退对应的时间区间添加着色效果,不采用双Y轴直方图的实现方式。之前找到的方案会强制图表显示完整X轴范围,无法进行缩放操作,需要修复该方案或寻找替代方案。

当前绘图代码:

fig, ax1=plt.subplots(figsize=(5,5))
ax2=ax1.twinx()
ax2.fill_between(df.index, 0,1,where=df['RECESSION'], alpha=0.4,transform=ax2.get_xaxis_transform())
ax1.plot(df['REL']['2022-09-01':'2022-12-01'],'b',linewidth=1)
ax2.plot(df['US10']['2022-09-01':'2022-12-01'],'r--',linewidth=1)

对应的数据集:

US10    REL         RECESSION
Dates           
2022-06-05  2.92    0.826972    0.0
2022-06-12  3.04    0.821700    1.0
2022-06-19  3.28    0.831073    1.0
2022-06-26  3.09    0.822982    1.0
2022-07-03  2.98    0.823109    0.0
2022-07-10  3.01    0.812530    0.0
2022-07-17  2.96    0.806165    0.0
2022-07-24  2.91    0.807227    0.0
2022-07-31  2.68    0.806655    0.0
2022-08-07  2.68    0.803642    0.0
2022-08-14  2.87    0.817092    0.0
2022-08-21  2.88    0.814631    0.0
2022-08-28  3.03    0.810260    0.0
2022-09-04  3.26    0.820891    0.0
2022-09-11  3.29    0.828855    0.0
2022-09-18  3.45    0.838984    0.0
2022-09-25  3.70    0.839056    0.0
2022-10-02  3.76    0.829300    0.0
2022-10-09  3.83    0.828128    0.0
2022-10-16  3.97    0.835641    0.0
2022-10-23  4.24    0.841246    0.0
2022-10-30  3.96    0.845483    0.0
2022-11-06  4.14    0.855199    1.0
2022-11-13  3.82    0.853006    1.0
2022-11-20  3.77    0.848167    1.0
2022-11-27  3.71    0.852128    1.0
2022-12-04  3.53    0.846362    1.0
2022-12-11  3.48    0.843546    1.0
2022-12-18  3.44    0.844612    1.0
2022-12-25  3.67    0.859020    1.0
2023-01-01  3.83    0.862859    1.0
2023-01-08  3.71    0.872137    1.0
2023-01-15  3.43    0.863680    1.0
2023-01-22  NaN     NaN         1.0
2023-01-29  NaN     NaN         1.0

解决方案

问题原因分析

之前的方案中,fill_between使用了完整的df.index,加上transform=ax2.get_xaxis_transform(),会强制Matplotlib显示整个X轴时间范围,导致无法缩放。另外,get_xaxis_transform()将Y轴坐标归一化到0-1,但不对数据做时间范围过滤的话,会直接锁定X轴范围。

修复方案1:过滤时间范围后使用fill_between

先截取和绘图一致的时间范围,在该范围内绘制填充,同时避免强制锁定X轴:

import matplotlib.pyplot as plt

# 定义绘图的时间范围
start_date = '2022-09-01'
end_date = '2022-12-01'
filtered_df = df.loc[start_date:end_date]

fig, ax1 = plt.subplots(figsize=(5,5))
ax2 = ax1.twinx()

# 在过滤后的时间范围内绘制衰退填充,覆盖整个Y轴高度
ax1.fill_between(filtered_df.index, 
                 ax1.get_ylim()[0], ax1.get_ylim()[1], 
                 where=filtered_df['RECESSION'] == 1, 
                 alpha=0.4, color='gray', zorder=0)

# 绘制两条曲线
ax1.plot(filtered_df['REL'], 'b', linewidth=1)
ax2.plot(filtered_df['US10'], 'r--', linewidth=1)

# 可选:设置Y轴标签
ax1.set_ylabel('REL', color='b')
ax2.set_ylabel('US10', color='r')

plt.show()

修复方案2:使用axvspan遍历衰退区间

提取所有连续的衰退区间,用axvspan逐个绘制,这种方式完全支持缩放,因为每个区间都是独立的轴元素:

import matplotlib.pyplot as plt
import pandas as pd

# 提取衰退区间的起始和结束日期
df['RECESSION_SHIFT'] = df['RECESSION'].shift(1)
# 找到从0变1的起始点
start_points = df[(df['RECESSION'] == 1) & (df['RECESSION_SHIFT'] == 0)].index
# 找到从1变0的结束点
end_points = df[(df['RECESSION'] == 0) & (df['RECESSION_SHIFT'] == 1)].index

# 处理最后一个区间持续到末尾的情况
if df.iloc[-1]['RECESSION'] == 1:
    end_points = end_points.append(pd.Index([df.index[-1]]))

# 定义绘图时间范围
start_date = '2022-09-01'
end_date = '2022-12-01'

fig, ax1 = plt.subplots(figsize=(5,5))
ax2 = ax1.twinx()

# 绘制所有符合时间范围的衰退区间
for start, end in zip(start_points, end_points):
    # 只保留在当前绘图范围内的区间部分
    actual_start = max(start, pd.Timestamp(start_date))
    actual_end = min(end, pd.Timestamp(end_date))
    if actual_start < actual_end:
        ax1.axvspan(actual_start, actual_end, alpha=0.4, color='gray', zorder=0)

# 绘制曲线
ax1.plot(df['REL'].loc[start_date:end_date], 'b', linewidth=1)
ax2.plot(df['US10'].loc[start_date:end_date], 'r--', linewidth=1)

# 可选:设置Y轴标签
ax1.set_ylabel('REL', color='b')
ax2.set_ylabel('US10', color='r')

plt.show()

关键说明

  • 方案1通过过滤数据到绘图范围,避免X轴被强制拉满,同时用ax1.get_ylim()让填充覆盖整个Y轴高度,不影响双Y轴显示。
  • 方案2通过提取连续衰退区间,用axvspan绘制,完全兼容缩放操作,因为每个区间都是基于轴坐标的元素,缩放时会自动调整显示。
  • 两种方案都无需使用transform=ax2.get_xaxis_transform(),避免了Y轴归一化带来的问题,同时保证缩放功能正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:50:20