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

如何绘制按年份区分、横轴为年月纵轴为数值的时序散点图

问题:绘制按年份上色的年月横轴能耗图表

我想要绘制横轴为所有年份-月份、纵轴为月度能耗均值的图表,同时按数据所属年份为数据点上色。使用小时能耗数据集尝试后未得到预期效果。


现有代码

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.colors as mcolors
colors_list = list(mcolors.XKCD_COLORS.keys())

df = pd.read_csv('/kaggle/input/hourly-energy-consumption/DOM_hourly.csv')
df.set_index('Datetime', inplace=True, drop=True)
df.index = pd.to_datetime(df.index, format='%Y-%m-%d %H:%M:%S')
# 去除重复索引
df = df[~df.index.duplicated(keep='first')]
# 月度均值数据框
mdf = df.resample(rule='M', kind='interval').mean()#.to_period('M').mean()
# 绘图
mdf['Year'] = mdf.index.year
mdf['Month'] = mdf.index.month
fig, ax = plt.subplots(figsize=(10, 6))
sns.scatterplot(x='Month', y=mdf.columns[0], data=mdf, hue='Year',ax=ax)
plt.show()

当前输出

当前输出图表

期望输出

我希望得到类似下图的效果,这样可以观察年度间的模式,也能查看多个月份的共性模式:
期望输出图表


尝试的代码(含警告)

我尝试了以下代码来实现期望效果,但出现了SettingWithCopyWarning警告:

# 绘制年度间同月变化图表
years_list = mdf['Year'].unique()
years_color = colors_list[:len(years_list)]
# 为主数据框添加颜色列
mdf['year_color'] = mdf['Year'].map(dict(zip(years_list,years_color)))

for one_month in range(1,13,1):
    one_month_all_years_data = mdf[mdf['Month']==one_month]
    x_ticks = np.linspace(0,1,len(one_month_all_years_data)+1,endpoint=False)[1:len(one_month_all_years_data)+1]
    one_month_all_years_data['All years-months'] = None
    one_month_all_years_data.loc[:,'All years-months'] = x_ticks + one_month
    ax = sns.scatterplot(x='All years-months',y=mdf.columns[0],data=one_month_all_years_data,
                   hue = one_month_all_years_data.index, hue_order = one_month_all_years_data['year_color'])
    sns.move_legend(ax, one_month_all_years_data.index)

plt.show()

警告信息

/tmp/ipykernel_32/2084798528.py:74: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  one_month_all_years_data['All years-months'] = None
/tmp/ipykernel_32/2084798528.py:75: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
........

当前接近期望的输出

当前接近期望的图表


解决方案

问题分析

  1. 原代码用Month作为x轴,导致所有年份的同月数据堆叠在同一位置,无法体现时间顺序
  2. 尝试代码中的切片赋值引发警告,且x轴处理逻辑复杂、图例设置错误

修正后的代码

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 读取并预处理数据
df = pd.read_csv('/kaggle/input/hourly-energy-consumption/DOM_hourly.csv')
df['Datetime'] = pd.to_datetime(df['Datetime'])
df = df.drop_duplicates(subset='Datetime', keep='first').set_index('Datetime')

# 计算月度均值,提取年月信息
mdf = df.resample('M').mean().reset_index()
mdf['Year'] = mdf['Datetime'].dt.year
mdf['Month'] = mdf['Datetime'].dt.month
# 生成连续的x轴数值:年份 + 月份占比(比如2015-01对应2015.0,2015-02对应2015.0833)
mdf['x_value'] = mdf['Datetime'].dt.year + (mdf['Datetime'].dt.month - 1)/12

# 绘图
fig, ax = plt.subplots(figsize=(12, 6))
sns.scatterplot(x='x_value', y=df.columns[0], data=mdf, hue='Year', palette='tab10', s=80, ax=ax)

# 设置x轴刻度:仅显示每年1月的年份标签
year_ticks = mdf.groupby('Year')['x_value'].first()
ax.set_xticks(year_ticks)
ax.set_xticklabels(year_ticks.index.astype(str))
# 添加月份分隔线,方便对比同月位置
for month in range(1, 13):
    ax.axvline(x=year_ticks.min() + (month-1)/12, color='lightgray', linestyle='--', alpha=0.5)

ax.set_xlabel('年份-月份')
ax.set_ylabel('月度能耗均值')
ax.set_title('年度月度能耗变化对比')
plt.tight_layout()
plt.show()

代码说明

  1. 数据预处理:简化日期转换逻辑,直接用resample('M')生成月度均值,避免索引类型问题
  2. x轴优化:将年月转换为连续数值,确保横轴按时间顺序排列,同一年的月份连续分布
  3. 可视化优化:使用内置配色方案tab10区分年份,添加月份分隔线方便观察年度间同月模式,同时解决了原代码的堆叠问题与赋值警告

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 11:27:55