使用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
相关产品推荐
相关产品推荐

