首页 > 解决方案 > Matplotlib pandas 以日期时间为索引的季度条形图不起作用

问题描述

我有一个索引为日期时间的熊猫系列,我试图使用条形图对其进行可视化。我的代码如下。但我得到的图表似乎不太准确(下图)。我该如何解决? 条形图

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(100)
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
s2 = pd.Series(np.random.randint(100,1000,size=(30)),index=dti)
df4 = s2.to_frame(name='count')
print('\ndf4:')
print(df4)
print(type(df4))
f2 = plt.figure("Quarterly",figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.bar(df4.index,df4['count'])
plt.tight_layout()
plt.show()

标签: pythonpandasmatplotlibtime-seriestimeserieschart

解决方案


不幸的是,matplotlib 的条形图似乎与 pandas 日期不符。

理论上,matplotlib 以天为单位表示条形宽度。但是,如果您尝试类似ax.bar(df4.index,df4['count'], width=30),您会看到带有极宽条形的情节,几乎完全填满了情节。尝试使用width,发生了一些奇怪的事情。当width小于 2 时,它看起来像是以天为单位表示的。但是如果width大于 2,它会突然跳到更宽的地方。

在我的系统(matplotlib 3.1.2、pandas 0.25.3、Windows)上,它看起来像: 默认图

一种解决方法是使用 pandas 的条形图。这些似乎使条形图分类,每个条形图有一个刻度。它们会被标记为完整的日期,包括小时、分钟和秒。您可以重新标记它们,例如:

df4.plot.bar(y='count', width=0.9, ax=ax)
plt.xticks(range(len(df4.index)),
           [t.to_pydatetime().strftime("%b '%y") for t in df4.index],
           rotation=90)

进一步调查,matplotlib 条形宽度的不一致跳跃似乎与frequency熊猫时代的构建有关。因此,一个解决方案可能是将日期转换为 matplotlib 日期。试试这个,是的,宽度以天为单位表示一致。

不幸的是,季度日期之间的天数并不完全相同,导致一些条形太宽,而另一些条形太窄。下一个问题的解决方案是明确计算每个柱的天数。为了在条之间获得良好的分离,将它们的边缘绘制为白色会有所帮助。

from datetime import datetime

x = [datetime.date(t) for t in df4.index]  # convert the pandas datetime to matplotlib's
widths = [t1-t0 for t0, t1 in zip(x, x[1:])]  # time differences between dates
widths += [widths[-1]] # the very last bar didn't get a width, just repeat the last width
ax.bar(x, df4['count'], width=widths, edgecolor='white')

结果图


推荐阅读