绘制 Timedelta 系列的 Pandas,在选定时间带有垂直线

pro*_*lle 2 python matplotlib timedelta pandas

我有一个与此非常相似的问题:Pandas 绘制时间序列图,在选定日期使用垂直线,但该解决方案不适用于 Timedelta。

考虑这个系列:

In:
avg_hr.head()

Out:
00:00:00     69.000000
00:00:01     93.750000
00:00:02     93.125000
00:00:03     92.900000
00:00:04     93.222222
00:00:05     93.222222
...
Name: bpm, Length: 253, dtype: float64
Run Code Online (Sandbox Code Playgroud)

我可以像这样选择本系列中的元素:

In:
avg_hr[pd.Timedelta(seconds=3)]

Out:
92.9
Run Code Online (Sandbox Code Playgroud)

我可以生成这样的图表:

In:
avg_hr.plot()
Run Code Online (Sandbox Code Playgroud)

avg_hr.plot()

但是,我不能像这样用 TimeDelta 绘制垂直线:

In:
plt.axvline(x=pd.Timedelta(seconds=110), color='r', linestyle='dashed', linewidth=2)

Out:
TypeError: Cannot compare type 'Timedelta' with type 'float64'
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用 float 或 int,则垂直线出现在位置 0。

In:
plt.axvline(x=110, color='r', linestyle='dashed', linewidth=2)
Run Code Online (Sandbox Code Playgroud)

avg_hr.plot()

如何使用此 timedelta 索引绘制垂直线?

编辑:

即使我直接使用 x 轴上使用的键,我也遇到了同样的错误:

In:
for key in avg_hr.keys():
    ax.axvline(x=key, color='r', linestyle='dashed', linewidth=2)

Out:
TypeError: Cannot compare type 'Timedelta' with type 'float64'
Run Code Online (Sandbox Code Playgroud)

pro*_*lle 8

我发现即使我以秒为单位工作,并且轴标签以秒为单位显示时间,但实际上以纳秒为单位!

从文档Pandas Time Deltas

Pandas 使用 64 位整数以纳秒分辨率表示 Timedeltas

因此,在我的问题示例中,当我调用它时,垂直线不在位置 0,但实际上在位置 110 纳秒(因此非常接近 0 与此比例):

plt.axvline(x=110, color='r', linestyle='dashed', linewidth=2)
Run Code Online (Sandbox Code Playgroud)

解决方案只是以纳秒为单位转换您的 x 值:

x_ns = pd.Timedelta(seconds=110) / pd.Timedelta(1,'ns') #Seconds to nanoseconds
plt.axvline(x=x_ns, color='r', linestyle='dashed', linewidth=2)
Run Code Online (Sandbox Code Playgroud)

我在尝试更改 xlim 时发现了这一点,然后我看到一切都缩放到了纳秒级。因此,需要对 xlim 应用相同的转换。

ax1.set_xlim([0, 110])
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

多条垂直线的结果

在此处输入图片说明

完成:

#Add verticals lines for specific event
plt.axvline(x=pd.Timedelta(seconds=120) / pd.Timedelta(1,'ns'), color='r', linestyle='dashed', linewidth=2)
plt.axvline(x=pd.Timedelta(seconds=185) / pd.Timedelta(1, 'ns'), color='r', linestyle='dashed', linewidth=2)
plt.axvline(x=pd.Timedelta(seconds=210) / pd.Timedelta(1, 'ns'), color='r', linestyle='dashed', linewidth=2)
plt.axvline(x=pd.Timedelta(seconds=225) / pd.Timedelta(1, 'ns'), color='r', linestyle='dashed', linewidth=2)
Run Code Online (Sandbox Code Playgroud)