python - 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()
解决方案
不幸的是,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')
推荐阅读
- node.js - Laravel 混合模块解析失败:意外令牌 (18:20)
- excel - 如何将 MROUND 与 if then 公式结合起来
- python - 如何键入深度嵌套的字典和列表结构
- javascript - 在 Electron 中,如何通过 preload.js 中定义的全局变量使 ipcRenderer 可用于多个渲染器进程?
- node.js - 如何为 Node.js 和 Express Controller->Service->Repository 架构构建流响应?
- gpu - 尽管有更好的 GPU,但在 Google Colab 上的训练比在本地机器上的训练要慢 - 为什么?
- javascript - TypeError:fs.createReadStream 不是函数 [React]
- javascript - Javascript:为什么数字模式在打字时不起作用?
- python - 我如何通过 Windows 发送一个 scapy 数据包
- android - 模拟器中 AOSP 上的 ASAN 未捕获内存错误