如何避免Pandas绘图时将索引转为Period类型?
解决Pandas df.plot()与NBER衰退阴影函数的兼容问题
我需要绘制时间序列数据并添加NBER衰退期的灰色阴影(类似Matlab的recessionplot()),为此编写了add_nber_shade函数,但使用Pandas的df.plot()绘图时出现TypeError: <class 'pandas._libs.tslibs.period.Period'> is not convertible to datetime错误,原因是Pandas自动将索引转为了Period类型,导致原函数无法处理。以下是两种解决方案:
方案1:修复add_nber_shade函数,兼容Period类型
修改函数中提取最小年份的逻辑,统一处理datetime和Period类型的x轴数据:
def add_nber_shade(ax: plt.Axes, nber_df: pd.DataFrame, alpha: float=0.2): """ Adds NBER recession shades to a single plt.axes (typically an "ax"). Args: ax (plt.Axes): The ax you want to change with data already plotted nber_df (pd.DataFrame): the Pandas dataframe with a "start" and an "end" column alpha (float): transparency Returns: plt.Axes: returns the same axes but with shades """ # 统一转换x轴最小数据为Timestamp,兼容datetime和Period类型 x_min = min(ax.lines[0].get_xdata()) min_year = pd.Timestamp(x_min).year nber_to_keep = nber_df[pd.to_datetime(nber_df["start"]).dt.year >= min_year] for start, end in zip(nber_to_keep["start"], nber_to_keep["end"]): ax.axvspan(start, end, color = "gray", alpha = alpha) return ax
关键修改说明
使用pd.Timestamp()可以直接将datetime或Period类型的对象转换为时间戳,无需额外判断类型,避免了原代码中pd.to_datetime()无法处理Period的问题。
方案2:阻止Pandas自动转换索引为Period类型
在调用df.plot()时添加x_compat=True参数,强制Pandas保留原始的datetime索引类型:
import pandas as pd import numpy as np import matplotlib.pyplot as plt df = pd.DataFrame(np.random.randn(3000, 2), columns=list('AB'), index=pd.date_range(start='1970-01-01', periods=3000, freq='W')) # 使用x_compat=True阻止索引转为Period ax = df.plot(y='A', lw=0.2, x_compat=True) add_nber_shade(ax, nber) plt.show()
原理说明
x_compat=True会让Pandas采用与matplotlib原生绘图一致的时间轴处理方式,不自动将datetime索引转换为Period类型,原函数即可正常运行。
内容的提问来源于stack exchange,提问作者Raul Guarini Riva
相关产品推荐
相关产品推荐

