Python 使用pandas和Matplotlib自定义日期时间索引的分组条形图

Python 使用pandas和Matplotlib自定义日期时间索引的分组条形图,python,pandas,matplotlib,Python,Pandas,Matplotlib,我想创建一个分组条形图,显示一个自定义的日期-时间索引-只显示月份和年份,而不是完整的日期。我希望钢筋分组,而不是堆叠 我认为熊猫可以很容易地处理这个问题,使用: 将熊猫作为pd导入 将matplotlib.pylab作为plt导入 将matplotlib.dates导入为mdates testdata=pd.DataFrame({“A”:[1,2,3] ,“B”:[2,3,1] ,“C”:[2,3,1]} ,index=pd.to_datetime(pd.DatetimeIndex( 数据=[

我想创建一个分组条形图,显示一个自定义的日期-时间索引-只显示月份和年份,而不是完整的日期。我希望钢筋分组,而不是堆叠

我认为熊猫可以很容易地处理这个问题,使用:

将熊猫作为pd导入
将matplotlib.pylab作为plt导入
将matplotlib.dates导入为mdates
testdata=pd.DataFrame({“A”:[1,2,3]
,“B”:[2,3,1]
,“C”:[2,3,1]}
,index=pd.to_datetime(pd.DatetimeIndex(
数据=[“2019-03-02”、“2019-04-01”、“2019-05-01”])
ax=testdata.plot.bar()
这就创造了我想要的情节,我只想把日期改成更简单的,比如2019年3月,2019年4月,2019年5月

我认为使用自定义日期格式化程序可以工作,所以我尝试了

ax.xaxis.set\u major\u定位器(mdates.MonthLocator())
ax.xaxis.set\u major\u格式化程序(mdates.DateFormatter(“%b%Y”))
但是我的标签完全消失了。这意味着熊猫和DateFormatter的关系有点困难。因此,我尝试使用Matplotlib基础知识:

fig,ax=plt.subplot()
宽度=0.8
ax.bar(testdata.index,testdata[“A”])
ax.bar(testdata.index,testdata[“B”])
ax.bar(testdata.index,testdata[“C”])
ax.xaxis.set\u major\u定位器(mdates.MonthLocator())
ax.xaxis.set\u major\u格式化程序(mdates.DateFormatter(“%b%Y”))
plt.show()
现在,日期表示如预期的那样(尽管空格可以减少),但是数据重叠,这没有帮助

由于我使用的是DateTime索引,所以定义一个宽度并从x值中减去它(通常建议这样做)不会有帮助。我得到一个错误,即不支持减去DatetimeIndes和float

fig,ax=plt.subplot()
宽度=0.8
ax.bar(testdata.index-width,testdata[“A”])
ax.bar(testdata.index,testdata[“B”])
ax.bar(testdata.index+宽度,testdata[“C”])
ax.xaxis.set\u major\u定位器(mdates.MonthLocator())
ax.xaxis.set\u major\u格式化程序(mdates.DateFormatter(“%b%Y”))
plt.show()

所以现在我的想法已经没有了,我希望输入的内容是分类的。所以,也许你想得太多了,只想用你想在轴上看到的字符串作为分类标签作为索引

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({"A": [1, 2, 3]
                       ,"B": [2, 3, 1]
                       , "C": [2, 3, 1]}  
                       ,index=pd.to_datetime(pd.DatetimeIndex(
                            data=["2019-03-02", "2019-04-01","2019-05-01"])))

df.index = [d.strftime("%b %Y") for d in df.index]
ax = df.plot.bar()
plt.show()

原因
ax.xaxis.set_major_locator(mdates.MonthLocator())
失败,因为在引擎盖下,熊猫根据
范围(len(df))
绘制条形图,然后相应地重命名刻度

打印后,您可以抓取Xticklabel并重新设置格式:

ax = testdata.plot.bar()

ticks = [tick.get_text() for tick in ax.get_xticklabels()]
ticks = pd.to_datetime(ticks).strftime('%b %Y')
ax.set_xticklabels(ticks)
其结果与ImportanceOfBeingernest的结果相同:

另一种可能更好的方法是移动每列的栏。当您有许多列并且希望减少XTICK的数量时,这种方法效果更好

fig, ax = plt.subplots()

# define the shift
shift = pd.to_timedelta('1D')

# modify the base of each columns, can do with a for loop
ax.bar(testdata.index + shift, testdata["A"]) 
ax.bar(testdata.index, testdata["B"])
ax.bar(testdata.index - shift, testdata["C"])
ax.xaxis.set_major_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y'))
plt.show()
输出:


我们很高兴知道,pandas在内部忽略了索引的值,只是直接绘图。我会记住这一点,以备将来参考。熊猫如何处理内部绘图有一些文档吗?我没有这方面的参考资料,只是根据我的经验。