Python matplotlib绘制分季节周内逐时均值连续时序图
连续周逐时均值时序图实现方案
你当前代码无法实现折线连续排布的核心原因是:所有星期几的折线都使用0-23小时作为x轴坐标,导致7条线完全重叠在单日24小时区间内。只需为不同星期的小时值增加对应天数的偏移量,构造总长度168小时(7天*24小时)的连续x轴,再调整刻度标签即可匹配目标效果。
修改后可直接运行的完整代码
import pandas as pd import matplotlib.pyplot as plt import matplotlib as mpl import numpy as np # ---------------------- 1. 构造测试数据(和原逻辑一致) ---------------------- df = pd.DataFrame() df["date"] = pd.date_range(start='2018', end='2019', freq = "15Min") df=df.set_index(["date"]) dw_mapping={0: 'Mon', 1: 'Tue', 2: 'Wed', 3: 'Thu', 4: 'Fri', 5: 'Sat', 6: 'Sun'} df['Day']=df.index.weekday.map(dw_mapping) season_mapping={1: 'Winter', 2: 'Winter', 3: 'eS/lF', 4: 'eS/lF', 5: 'lS/eF', 6: 'Summer', 7: 'Summer', 8: 'Summer', 9: 'lS/eF', 10:'eS/lF', 11:'eS/lF', 12:'Winter'} df['season']=df.index.month.map(season_mapping) df["B1W"] = 1 df['B1W'] = np.where(df['season'] == 'Winter', df['B1W'] * np.random.randint(30, 60, df.shape[0]), df["B1W"]) df['B1W'] = np.where(df['season'] == 'eS/lF', df['B1W'] * np.random.randint(20, 50, df.shape[0]), df["B1W"]) df['B1W'] = np.where(df['season'] == 'lS/eF', df['B1W'] * np.random.randint(10, 30, df.shape[0]), df["B1W"]) df['B1W'] = np.where(df['season'] == 'Summer', df['B1W'] * np.random.randint(0, 10, df.shape[0]), df["B1W"]) # ---------------------- 2. 绘图配置 ---------------------- mpl.rcParams['figure.dpi'] = 100 plt.style.use('ggplot') ymin, ymax = 0, 60 # 固定星期顺序 day_list = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] # 子图和季节的映射关系 season_ax_map = [ ("Summer", (0,0)), ("eS/lF", (0,1)), ("lS/eF", (1,0)), ("Winter", (1,1)) ] fig, axes = plt.subplots(2, 2) plt.subplots_adjust(wspace=0.2, hspace=0.3, bottom=0.2) fig.suptitle("Building 1", fontsize=16) fig.set_figheight(10) fig.set_figwidth(15) # ---------------------- 3. 分季节绘制连续折线 ---------------------- for season, (ax_row, ax_col) in season_ax_map: ax = axes[ax_row, ax_col] # 筛选当前季节数据,固定星期字段顺序 season_data = df.loc[df["season"]==season].copy() season_data['Day'] = pd.Categorical(season_data['Day'], categories=day_list, ordered=True) # 计算分星期、分小时的均值 hourly_avg = season_data.groupby([season_data.index.hour, 'Day'])["B1W"].mean().unstack() # 为每个星期的小时值加24*天数偏移,构造连续x轴 for day_idx, day_name in enumerate(day_list): x = np.arange(24) + day_idx * 24 y = hourly_avg[day_name].values ax.plot(x, y, label=day_name) # 坐标轴配置 ax.set_ylim(ymin, ymax) ax.set_title(season) ax.set_ylabel('Power in MW') # x轴刻度对应每天起始位置,标签为星期名 ax.set_xticks(np.arange(0, 7*24, 24)) ax.set_xticklabels(day_list) ax.set_xlabel('Time') # 统一配置底部图例 handles, labels = axes[1,1].get_legend_handles_labels() axes[1,1].legend(handles, labels, loc=1, ncol=7, bbox_to_anchor=(0.638,-0.2), frameon=True) plt.show()
关键改动说明
- 提前固定周一到周日的排序规则,避免分组聚合后星期顺序错乱
- 不再将0-23小时作为统一x轴,而是给每个星期的小时值增加
星期序号*24的偏移量,构造总长度168小时的连续时间轴,实现7天折线首尾相接 - 调整x轴刻度位置为每天的0点位置(0、24、48...144),刻度标签替换为对应星期名,和目标效果图的坐标轴样式完全匹配
- 保留了原有的子图布局、配色风格、标题与图例位置,无需调整原有可视化配置习惯
目标效果参考:
原实现效果参考:
内容的提问来源于stack exchange,提问作者Freedo
相关产品推荐
相关产品推荐



