以datetime为索引的Matplotlib季度条形图不起作用

2024-04-26 04:50:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个熊猫系列,索引为datetime,我正试图将其可视化, 使用条形图。我的代码如下。但我得到的图表似乎不太准确(下图)。我该如何解决这个问题? bar chart

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()

Tags: importdatetimeindexascountnppltrandom
2条回答

您可以通过^{}中的width参数将条的宽度设置为大于默认值0.8的某个值

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')
f2 = plt.figure("Quarterly",figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.bar(df4.index,df4['count'], width=70)
plt.tight_layout()
plt.show()

enter image description here

在这种情况下,宽度被解释为以天为单位的标量


编辑

出于某些原因,上述方法仅适用于旧版本的matplotlib(测试版本为2.2.3)。为了使用当前(3.1.2)版本,必须进行以下修改:

# ...
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
dti = [pd.to_datetime(t) for t in dti]
# ...

这将在设置钢筋宽度时产生正确的行为

不幸的是,matplotlib的条形图似乎不能很好地配合熊猫的约会

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

在我的系统(matplotlib 3.1.2、0.25.3、Windows)上,它看起来像: default plot

解决方法使用熊猫的条形图。这些似乎使酒吧分类,每个酒吧有一个勾号但是他们会被标上完整的日期,包括小时、分钟和秒。您可以重新标记它们,例如:

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')

resulting plot

相关问题 更多 >