You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pandas和Matplotlib时YearLocator显示错误年份1970的问题

月度订单柱状图年度刻度显示异常问题

我用以下代码绘制月度订单柱状图,整体运行正常,但尝试通过YearLocator设置年度主刻度时,仅显示1970年的刻度,不清楚操作哪里有误。

from pandas import Timestamp
import pandas as pd
import matplotlib.dates as mdates

test_data = pd.Series({Timestamp('2016-10-31 00:00:00'): 1052,
 Timestamp('2016-11-30 00:00:00'): 942,
 Timestamp('2016-12-31 00:00:00'): 791,
 Timestamp('2017-01-31 00:00:00'): 982,
 Timestamp('2017-02-28 00:00:00'): 647,
 Timestamp('2017-03-31 00:00:00'): 966,
 Timestamp('2017-04-30 00:00:00'): 1289,
 Timestamp('2017-05-31 00:00:00'): 504,
 Timestamp('2017-06-30 00:00:00'): 496,
 Timestamp('2017-07-31 00:00:00'): 776,
 Timestamp('2017-08-31 00:00:00'): 869,
 Timestamp('2017-09-30 00:00:00'): 617,
 Timestamp('2017-10-31 00:00:00'): 1601,
 Timestamp('2017-11-30 00:00:00'): 1094,
 Timestamp('2017-12-31 00:00:00'): 1405,
 Timestamp('2018-01-31 00:00:00'): 1377,
 Timestamp('2018-02-28 00:00:00'): 921,
 Timestamp('2018-03-31 00:00:00'): 1229,
 Timestamp('2018-04-30 00:00:00'): 1374,
 Timestamp('2018-05-31 00:00:00'): 1045,
 Timestamp('2018-06-30 00:00:00'): 1222,
 Timestamp('2018-07-31 00:00:00'): 1119,
 Timestamp('2018-08-31 00:00:00'): 1610,
 Timestamp('2018-09-30 00:00:00'): 1525,
 Timestamp('2018-10-31 00:00:00'): 2160,
 Timestamp('2018-11-30 00:00:00'): 2414,
 Timestamp('2018-12-31 00:00:00'): 2004,
 Timestamp('2019-01-31 00:00:00'): 1751,
 Timestamp('2019-02-28 00:00:00'): 1069,
 Timestamp('2019-03-31 00:00:00'): 1524,
 Timestamp('2019-04-30 00:00:00'): 1758,
 Timestamp('2019-05-31 00:00:00'): 1568,
 Timestamp('2019-06-30 00:00:00'): 1221,
 Timestamp('2019-07-31 00:00:00'): 1097,
 Timestamp('2019-08-31 00:00:00'): 1671,
 Timestamp('2019-09-30 00:00:00'): 1212,
 Timestamp('2019-10-31 00:00:00'): 2468,
 Timestamp('2019-11-30 00:00:00'): 2591,
 Timestamp('2019-12-31 00:00:00'): 2516,
 Timestamp('2020-01-31 00:00:00'): 1842,
 Timestamp('2020-02-29 00:00:00'): 1704,
 Timestamp('2020-03-31 00:00:00'): 2314,
 Timestamp('2020-04-30 00:00:00'): 5300,
 Timestamp('2020-05-31 00:00:00'): 5499,
 Timestamp('2020-06-30 00:00:00'): 3815,
 Timestamp('2020-07-31 00:00:00'): 2368,
 Timestamp('2020-08-31 00:00:00'): 2844,
 Timestamp('2020-09-30 00:00:00'): 2269,
 Timestamp('2020-10-31 00:00:00'): 3138,
 Timestamp('2020-11-30 00:00:00'): 4584,
 Timestamp('2020-12-31 00:00:00'): 3674,
 Timestamp('2021-01-31 00:00:00'): 4831,
 Timestamp('2021-02-28 00:00:00'): 2978,
 Timestamp('2021-03-31 00:00:00'): 3318,
 Timestamp('2021-04-30 00:00:00'): 3477,
 Timestamp('2021-05-31 00:00:00'): 2601,
 Timestamp('2021-06-30 00:00:00'): 2134,
 Timestamp('2021-07-31 00:00:00'): 1709,
 Timestamp('2021-08-31 00:00:00'): 2663,
 Timestamp('2021-09-30 00:00:00'): 1877,
 Timestamp('2021-10-31 00:00:00'): 2210,
 Timestamp('2021-11-30 00:00:00'): 4441,
 Timestamp('2021-12-31 00:00:00'): 2782,
 Timestamp('2022-01-31 00:00:00'): 3666,
 Timestamp('2022-02-28 00:00:00'): 2546,
 Timestamp('2022-03-31 00:00:00'): 2207,
 Timestamp('2022-04-30 00:00:00'): 2881,
 Timestamp('2022-05-31 00:00:00'): 2682,
 Timestamp('2022-06-30 00:00:00'): 2550,
 Timestamp('2022-07-31 00:00:00'): 2362,
 Timestamp('2022-08-31 00:00:00'): 2834,
 Timestamp('2022-09-30 00:00:00'): 3012,
 Timestamp('2022-10-31 00:00:00'): 3425,
 Timestamp('2022-11-30 00:00:00'): 5092,
 Timestamp('2022-12-31 00:00:00'): 3289,
 Timestamp('2023-01-31 00:00:00'): 3719,
 Timestamp('2023-02-28 00:00:00'): 2788,
 Timestamp('2023-03-31 00:00:00'): 3499,
 Timestamp('2023-04-30 00:00:00'): 3493,
 Timestamp('2023-05-31 00:00:00'): 3402,
 Timestamp('2023-06-30 00:00:00'): 2828,
 Timestamp('2023-07-31 00:00:00'): 3525,
 Timestamp('2023-08-31 00:00:00'): 3739,
 Timestamp('2023-09-30 00:00:00'): 3278,
 Timestamp('2023-10-31 00:00:00'): 3548,
 Timestamp('2023-11-30 00:00:00'): 5150,
 Timestamp('2023-12-31 00:00:00'): 4719,
 Timestamp('2024-01-31 00:00:00'): 4679,
 Timestamp('2024-02-29 00:00:00'): 3222,
 Timestamp('2024-03-31 00:00:00'): 3374,
 Timestamp('2024-04-30 00:00:00'): 1421}, name="Monthly orders")

plot = test_data.plot(kind="bar",
               title="Monthly orders")

plot.xaxis.set_major_locator(mdates.YearLocator())  # Locate years
plot.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))  # Year format

代码运行结果:
错误的年度刻度显示


问题原因

pandas绘制柱状图时,会默认将时间索引转换为分类字符串标签,而非保留日期的数值型时间戳属性。YearLocator和DateFormatter仅对数值型的日期(即对应Unix时间戳的浮点数)生效,此时它们会把分类标签的索引值(从0开始的整数)当作时间戳处理,0对应的正是1970年1月1日,因此只会显示1970年的刻度。

解决方法

方案一:用Matplotlib原生方式绘制

绕过pandas的plot封装,直接用Matplotlib绘制柱状图,保留日期的数值属性:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

test_data = pd.Series(...)  # 你的数据

fig, ax = plt.subplots(figsize=(12, 6))
ax.bar(test_data.index, test_data.values)

# 设置年度主刻度
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
# 可选:添加月度次要刻度,增强可读性
ax.xaxis.set_minor_locator(mdates.MonthLocator())

plt.title("月度订单")
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

方案二:修改Pandas绘制后的x轴

如果坚持使用pandas的plot方法,需手动映射x轴刻度位置与对应日期:

import pandas as pd
import matplotlib.pyplot as plt

test_data = pd.Series(...)  # 你的数据

plot = test_data.plot(kind="bar", title="月度订单", figsize=(12, 6))

# 获取日期索引
dates = test_data.index
# 筛选每年第一个月份的位置和年份标签
year_positions = [i for i, dt in enumerate(dates) if dt.month == 1]
year_labels = [str(dt.year) for dt in dates if dt.month == 1]

# 设置主刻度为年度
plot.set_xticks(year_positions)
plot.set_xticklabels(year_labels)
# 设置次要刻度为月份,保留月度标签
plot.set_xticks(range(len(dates)), minor=True)
plot.set_xticklabels([dt.strftime('%b') for dt in dates], minor=True, rotation=45)

plt.tight_layout()
plt.show()

内容的提问来源于stack exchange,提问作者Snowflake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 22:09:52