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

自定义冬季年时间序列X轴调整及Python代码优化求助

问题解决:冬季年度周数折线图X轴显示优化及代码改进

问题背景

需要绘制冬季年(当年8月至次年8月)的每日事件数量折线图,X轴按35-53、1-34的顺序显示周数,每条曲线对应一个冬季年度。现有代码已生成正确排序的周索引表,但图表X轴仍按常规ISO周1-53排序:
当前图表

X轴显示问题解决方法

问题核心在于:即使重新索引了周数,pandas绘图时仍会按数字索引的自然顺序(1-53)渲染X轴。要实现自定义顺序,有两种可行方案:

方案1:将周索引转为字符串

把周数转换为字符串类型,让绘图时严格遵循列表定义的顺序:

order_weeks = [str(i) for i in range(35,54)] + [str(i) for i in range(1,35)]
# 先按数字索引匹配数据,再替换为字符串索引
datapiv = datapiv.reindex([int(w) for w in order_weeks])
datapiv.index = order_weeks
datapiv.plot(use_index=True)

方案2:手动指定X轴刻度与标签

保留数字索引,通过matplotlib API直接控制X轴显示内容:

import matplotlib.pyplot as plt

ax = datapiv.plot(use_index=True)
ax.set_xticks(range(len(order_weeks)))
ax.set_xticklabels(order_weeks)
plt.show()

代码优化建议

1. 用矢量化操作替代apply计算冬季年度

避免循环提升运行效率,直接基于日期索引的月份批量计算:

winter_base = np.where(data.index.month > 8, data.index.year, data.index.year - 1)
data["winter_year"] = "Winter " + winter_base.astype(str) + "-" + (winter_base + 1).astype(str)

2. 简化周数顺序生成

合并列表推导式,精简代码:

order_weeks = list(range(35, 54)) + list(range(1, 35))

3. 移除冗余中间列

year、date列仅用于计算冬季年度,完成后可删除以减少内存占用:

data = data.drop(columns=["year", "date"])

4. 用groupby+unstack替代pivot_table

针对简单聚合需求,该组合比pivot_table更直观高效:

datapiv = data.groupby(["week", "winter_year"])["count"].sum().unstack()

完整优化后代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 矢量化计算冬季年度
def get_winter_year(dates):
    winter_base = np.where(dates.month > 8, dates.year, dates.year - 1)
    return "Winter " + winter_base.astype(str) + "-" + (winter_base + 1).astype(str)

# 生成随机数据
np.random.seed(10)
data = pd.DataFrame({
    "dates": pd.date_range("2017-07-12", "2022-08-10"),
    "count": np.random.randint(150, size=len(pd.date_range("2017-07-12", "2022-08-10")))
}).set_index("dates")

# 计算周数与冬季年度
data["week"] = data.index.isocalendar().week
data["winter_year"] = get_winter_year(data.index)

# 聚合并按自定义周顺序排序
datapiv = data.groupby(["week", "winter_year"])["count"].sum().unstack()
order_weeks = list(range(35, 54)) + list(range(1, 35))
datapiv = datapiv.reindex(order_weeks)

# 绘图并设置X轴
ax = datapiv.plot(figsize=(12, 6))
ax.set_xticks(range(len(order_weeks)))
ax.set_xticklabels(order_weeks)
ax.set_xlabel("冬季年度周数")
ax.set_ylabel("事件总数")
plt.title("冬季年度每周事件数量趋势")
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 03:33:30