使用Pandas DataFrame绘图时X轴日期显示异常(显示1970年而非2024年)
Pandas堆叠柱状图X轴日期显示异常问题解决
问题描述
我有如下DataFrame,其中date列存储的是Timestamp对象:
| date | new | todo | fixed | close | |
|---|---|---|---|---|---|
| 0 | 2023-08-20 00:00:00+00:00 | 2 | 0 | 0 | 0 |
| 1 | 2023-08-27 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 2 | 2023-09-03 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 3 | 2023-09-10 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 4 | 2023-09-17 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 5 | 2023-09-24 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 6 | 2023-10-01 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 7 | 2023-10-08 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 8 | 2023-10-15 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 9 | 2023-10-22 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 10 | 2023-10-29 00:00:00+00:00 | 0 | 0 | 0 | 5 |
| 11 | 2023-11-05 00:00:00+00:00 | 0 | 0 | 0 | 3 |
| 12 | 2023-11-12 00:00:00+00:00 | 0 | 0 | 0 | 3 |
| 13 | 2023-11-19 00:00:00+00:00 | 0 | 0 | 0 | 1 |
| 14 | 2023-11-26 00:00:00+00:00 | 0 | 0 | 0 | 1 |
| 15 | 2023-12-03 00:00:00+00:00 | 0 | 0 | 0 | 1 |
| 16 | 2023-12-10 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 17 | 2023-12-17 00:00:00+00:00 | 0 | 0 | 0 | 1 |
| 18 | 2023-12-24 00:00:00+00:00 | 0 | 0 | 0 | 3 |
| 19 | 2023-12-31 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 20 | 2024-01-07 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 21 | 2024-01-14 00:00:00+00:00 | 0 | 1 | 1 | 0 |
| 22 | 2024-01-21 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 23 | 2024-01-28 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 24 | 2024-02-04 00:00:00+00:00 | 0 | 0 | 0 | 1 |
| 25 | 2024-02-11 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 26 | 2024-02-18 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 27 | 2024-02-25 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 28 | 2024-03-03 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 29 | 2024-03-10 00:00:00+00:00 | 0 | 0 | 1 | 0 |
| 30 | 2024-03-17 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 31 | 2024-03-24 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 32 | 2024-03-31 00:00:00+00:00 | 0 | 0 | 0 | 0 |
| 33 | 2024-04-07 00:00:00+00:00 | 0 | 0 | 0 | 1 |
尝试使用Pandas绘制堆叠柱状图时,柱状图本身显示正常,但X轴日期异常,显示为1970年左右的日期,而非数据中的2023-2024年。使用的代码如下:
matplotlib.use('agg') matplotlib.style.use('ggplot') fig, ax = plt.subplots(figsize=(16, 10)) df.plot( kind='bar', ax=ax, x='date', use_index=True, stacked=True, ) ax.xaxis.set_major_formatter(matplotlib.dates.AutoDateFormatter(ax.xaxis.get_major_locator())) ax.tick_params( 'x', labelrotation=75 ) ax.figure.savefig(f'fig/{filename}') plt.close(ax.figure)
经测试,直接使用matplotlib绘制单系列柱状图时X轴日期显示正常,代码如下:
ax.bar(df['date'], df['close'], width=3, )
问题原因
当使用Pandas的plot(kind='bar')并指定x='date'时,Pandas会将date列视为分类变量而非时间序列变量。此时X轴的底层刻度值是分类的索引(0、1、2...),而非原始的Timestamp值。之后用matplotlib.dates.AutoDateFormatter格式化这些索引值时,会把它们当作Unix时间戳(从1970-01-01开始的秒数),因此显示出1970年的异常日期。
解决方法
方法一:将date列设为DataFrame索引
把date列设置为DataFrame的索引,让Pandas识别其为时间序列,自动处理日期刻度:
matplotlib.use('agg') matplotlib.style.use('ggplot') # 将date列设为索引 df.set_index('date', inplace=True) fig, ax = plt.subplots(figsize=(16, 10)) df.plot( kind='bar', ax=ax, stacked=True, ) # 自定义日期显示格式 ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%Y-%m-%d')) ax.tick_params('x', labelrotation=75) ax.figure.savefig(f'fig/{filename}') plt.close(ax.figure)
方法二:手动设置X轴刻度标签
如果不想修改原DataFrame结构,可以直接提取date列的格式化字符串替换X轴刻度标签:
matplotlib.use('agg') matplotlib.style.use('ggplot') fig, ax = plt.subplots(figsize=(16, 10)) df.plot( kind='bar', ax=ax, x='date', stacked=True, use_index=True, ) # 替换刻度标签为格式化后的日期 ax.set_xticklabels(df['date'].dt.strftime('%Y-%m-%d')) ax.tick_params('x', labelrotation=75) ax.figure.savefig(f'fig/{filename}') plt.close(ax.figure)
注意事项
- 方法一更符合时间序列可视化的规范,Pandas会自动处理时间相关的刻度逻辑;
- 方法二更灵活,适合需要保留原DataFrame结构的场景;
- 注意代码中
df['close']的大小写,原测试代码中的CLOSED应为close(匹配DataFrame列名)。
内容的提问来源于stack exchange,提问作者Tradjincal
相关产品推荐
相关产品推荐

