0


Datawhale AI 夏令营 市场博弈和价格预测 EDA 探索性数据分析

前言

基于挑战赛“市场博弈和价格预测”
使用探索性数据分析(EDA)深入理解赛题。

对数据做尽可能多的探索,
了解数据所在的领域先验知识,数据本身的特性等,
(发现数据的结构、异常值、模式、趋势、关系以及变量之间的相互作用)
并总结为一系列有用的信息

0 编程准备

  1. !pip install numpy pandas seaborn matplotlib statsmodels
  2. import pandas as pd
  3. import seaborn as sns
  4. import matplotlib.pylab as plt
  5. from pathlib import Path
  6. import warnings
  7. warnings.filterwarnings('ignore')
  8. plt.style.use('ggplot')
  9. plt.rcParams['font.sans-serif']=['WenQuanYi Micro Hei',"SimHei"]
  10. plt.rcParams['axes.unicode_minus']=False
  11. base_path=Path("data")

请将数据文件electricity_price_parsed放在代码文件同级的data文件夹路径
下载链接:https://linklearner.com/activity/12/2/2 => 左上角打开面板 => 选择“Tsak 2”

1 数据基本信息

在这里插入图片描述
读取数据,并按照 NAN 划分训练集&测试集
代码

  1. electricity_price = pd.read_csv(base_path/"electricity_price_parsed.csv", parse_dates=["timestamp"], index_col=0)
  2. electricity_price.columns =["demand","price"]
  3. electricity_price.head()# 创建测试集掩码,标记出所有价格为 NaN 的数据行
  4. test_mask = electricity_price["price"].isna()# 创建训练集掩码,标记出所有价格不为 NaN 的数据行,其中~代表布尔取反,即TrueFalse互换。 `[True,False]` `~[False,True]`一致
  5. train_mask =~test_mask
  6. # 打印训练集的范围和总长度# 训练集范围从训练集中最早的日期到最新的日期print(f"训练集范围:{electricity_price[train_mask].index.min()} --> {electricity_price[train_mask].index.max()}\t总长度{len(electricity_price[train_mask])}")# 打印测试集的范围和总长度# 测试集范围从测试集中最早的日期到最新的日期print(f"测试集范围:{electricity_price[test_mask].index.min()} --> {electricity_price[test_mask].index.max()}\t总长度{len(electricity_price[test_mask])}")
  7. electricity_price.info()
  8. electricity_price.head(12)

回显
在这里插入图片描述
自定义函数 确认
代码

  1. defcheck_repeated(data, repeat_count=4):"""
  2. 检查给定数据序列中是否存在元素不断重复的情况。
  3. 参数:
  4. data (list): 要检查的序列数据。
  5. repeat_count (int): 每个元素应重复的次数。默认值为4。
  6. 返回:
  7. None
  8. """# 以步长 repeat_count 遍历 data 的索引for i inrange(0,len(data), repeat_count):# 从索引 i 开始,取长度为 repeat_count 的子序列
  9. subsequence = data[i:i + repeat_count]# 如果子序列的独特元素数量不等于 1,则表示不是同一元素重复iflen(set(subsequence))!=1:print(f"序列数据不是元素不断重复 {repeat_count} 次")return# 发现不满足条件的情况后,直接返回# 如果遍历完所有子序列,未发现不满足条件的情况,则输出满足条件的信息print(f"序列数据是元素不断重复 {repeat_count} 次")# 调用函数并传入特定的电价数据
  10. check_repeated(electricity_price[train_mask]["price"])

回显

  1. 序列数据是元素不断重复 4

使用 matplotlib.pylab 库画图确认
代码

  1. # 使用loc方法选择指定日期的数据,绘制价格图表
  2. electricity_price.loc["2023-01-03"].plot(y="price", figsize=(18,5), marker='o')# 设置图表的标题
  3. plt.title("2023年1月3日出清价格走势")

回显

Text(0.5, 1.0, ‘2023年1月3日出清价格走势’)
在这里插入图片描述

2 统计指标分析

鼠标右键 -> 在新标签页中打开图像
在这里插入图片描述
最基本的单变量数值关系
*可以使用

  1. electricity_price.describe()

快速生成描述性统计信息*

中心趋势

  • 均值:df[feature].mean()
  • 中位数 df[feature].median()
  • 最大值 df[feature].max()
  • 最小值 df[feature].min()
  • 众数 df[feature].mode()

变异程度

  • 标准差 df[feature].std()
  • 极差 df[feature].apply(lambda x: x.max() - x.min())
  • 四分位数 df[feature].quantile([0.25, 0.5, 0.75])
  • 变异系数 df[feature].std()/df[feature].mean()
  • 偏度和峰度 df[feature].skew(), df[feature].kurtosis()

变化率

  1. df[feature].pct_change()
  • 计算公式为 x 2 − x 1 x 1 \frac{x_2 - x_1}{x_1} x1​x2​−x1​​
    总负荷的 数值分布

代码

  1. # 使用 Seaborn 库绘制总负荷数值的分布图# sns.displot(...) 函数用于绘制数据的分布图
  2. ax = sns.displot(
  3. electricity_price,# 输入数据,包含绘制所需的列
  4. x="demand",# 指定绘图的列,这里是 "demand"
  5. aspect=1.5,# 图形的宽高比,1.5 表示宽度是高度的 1.5
  6. height=5,# 图形的高度设置为 5 英寸
  7. kde=True# 启用核密度估计(KDE),用于绘制数据的平滑概率密度曲线)# 设置图形的标题
  8. ax.set(title="总负荷数值分布")

回显

在这里插入图片描述

出清价格 数值分布
代码

  1. ax=sns.displot(electricity_price,x="price",aspect=1.5,height=5,kde=True);
  2. ax.set(title="出清价格数值分布")

回显

在这里插入图片描述

3 分时统计指标分析

线图

鼠标右键 -> 在新标签页中打开图像
在这里插入图片描述
不同年份的分时 电价 线图不同年份的分时 总负荷 线图
代码

  1. # 从 DataFrame 的索引中提取时间信息,并添加为新的列# 假设索引为 DatetimeIndex 类型# 提取小时信息,并创建一个新列 "hour"
  2. electricity_price["hour"]= electricity_price.index.hour
  3. # 提取月份信息,并创建一个新列 "month"
  4. electricity_price["month"]= electricity_price.index.month
  5. # 提取日期信息,并创建一个新列 "day"
  6. electricity_price["day"]= electricity_price.index.day
  7. # 提取星期几的信息(0 = 周一, 6 = 周日),并创建一个新列 "weekday"
  8. electricity_price["weekday"]= electricity_price.index.weekday
  9. # 提取年份信息,并创建一个新列 "year"
  10. electricity_price["year"]= electricity_price.index.year
  11. # 创建一个包含两个子图的绘图区域,图形大小为 20x9 英寸,并启用约束布局
  12. fig, ax = plt.subplots(1,# 子图的行数为 12,# 子图的列数为 2
  13. figsize=(20,9),# 设置整个图形的大小为 20x9 英寸
  14. constrained_layout=True# 启用约束布局以自动调整子图位置和大小)# 绘制不同年份的分时电价线图
  15. sns.lineplot(
  16. electricity_price.groupby(["hour","year"])["price"].mean().reset_index(),# 按小时和年份分组,计算每组的平均电价,并重置索引
  17. x="hour",# x 轴数据为小时
  18. y="price",# y 轴数据为平均电价
  19. ax=ax[0],# 将图绘制到第一个子图 (ax[0])
  20. marker="o",# 数据点标记为圆圈
  21. hue="year",# 根据年份不同设置不同的颜色
  22. palette="Set1"# 使用 "Set1" 调色板)
  23. ax[0].set_title("不同年份的分时电价")# 设置第一个子图的标题
  24. ax[0].set_xticks(range(24))# 设置 x 轴刻度为 0 23(小时范围)# 绘制不同年份的分时总负荷线图
  25. sns.lineplot(
  26. electricity_price.groupby(["hour","year"])["demand"].mean().reset_index(),# 按小时和年份分组,计算每组的平均总负荷,并重置索引
  27. x="hour",# x 轴数据为小时
  28. y="demand",# y 轴数据为平均总负荷
  29. ax=ax[1],# 将图绘制到第二个子图 (ax[1])
  30. marker="o",# 数据点标记为圆圈
  31. hue="year",# 根据年份不同设置不同的颜色
  32. palette="Set1"# 使用 "Set1" 调色板)
  33. ax[1].set_title("不同年份的分时总负荷")# 设置第二个子图的标题
  34. ax[1].set_xticks(range(24));# 设置 x 轴刻度为 0 23(小时范围)

回显

在这里插入图片描述

透视表&热力图

鼠标右键 -> 在新标签页中打开图像
在这里插入图片描述
不同月份的分时 电价 透视表
代码

  1. # 创建一个透视表,计算不同月份和时间下的电价
  2. pivot = pd.pivot_table(
  3. electricity_price,# 输入的 DataFrame
  4. values="price",# 透视表中要填充的值,这里是 "price"
  5. index="month",# 设置行索引为月份
  6. columns="hour"# 设置列索引为小时)# 将透视表中的数据类型转换为整数
  7. pivot = pivot.astype(int)
  8. pivot

回显

在这里插入图片描述

不同月份的分时 电价 热力图
代码

  1. # 创建一个图形,大小为 17x10 英寸
  2. plt.figure(figsize=(17,10))# 绘制热图,显示不同月份和时间下的电价
  3. sns.heatmap(
  4. pivot,# 透视表数据
  5. cmap="coolwarm",# 使用 "coolwarm" 调色板,显示热图的颜色
  6. linewidths=0.5,# 设置单元格之间的分隔线宽度为 0.5
  7. annot=True,# 启用单元格值的注释
  8. fmt=".0f",# 注释的格式为整数
  9. annot_kws={"size":12,# 注释文本的大小设置为 12"weight":"bold",# 注释文本的字体加粗"color":"black"}# 注释文本的颜色为黑色)# 设置图形的标题
  10. plt.title("不同月份和时间下的电价")

回显

在这里插入图片描述

4 负电价形成原因分析

鼠标右键 -> 在新标签页中打开图像
在这里插入图片描述
负电价频数 出现的小时分布
代码

  1. minus_mask = electricity_price["price"]<0
  1. plt.figure(figsize=(12,7))
  2. ax = sns.countplot(electricity_price[minus_mask], x="hour")
  3. ax.set(title="负电量频数出现的小时分布")

回显

在这里插入图片描述

负电价频数 出现的月分布
代码

  1. plt.figure(figsize=(12,7))
  2. ax = sns.countplot(electricity_price[minus_mask], x="month")
  3. ax.set(title="负电量频数出现的月分布")

回显

在这里插入图片描述

负电价频数 出现的日期排序数表
代码

  1. (# 选择不满足 minus_mask 条件的数据
  2. electricity_price[minus_mask]# 按月份和日期分组,计算每个组合的记录数量.groupby(["month","day"]).size()# 计算每个分组的大小(即每个分组的记录数).reset_index(name='count')# 重置索引,使 groupby 结果成为 DataFrame,并保留分组字段为列.sort_values("count",# "count" 列排序
  3. ascending=False)# 降序排序.head(15)# 选择排序后的前 15 行)

回显

在这里插入图片描述

2022年5月1日 - 2022年5月9日 电价 线图
代码

  1. # 创建一个图形,大小为 20x8 英寸
  2. plt.figure(figsize=(20,8))# 绘制从 202251日到202259日的电价数据的折线图
  3. ax = sns.lineplot(
  4. electricity_price.loc["2022-05-01":"2022-05-09"]["price"],# DataFrame 中选择时间范围内的电价数据
  5. color="black"# 设置折线的颜色为黑色)# 在每一天的 10:00 到 15:00 之间添加黄色半透明的高亮区域for i inrange(1,10):
  6. ax.axvspan(f"2022-05-0{i} 10:00:00",# 高亮区域的开始时间f"2022-05-0{i} 15:00:00",# 高亮区域的结束时间
  7. color='yellow',# 高亮区域的颜色为黄色
  8. alpha=0.2# 高亮区域的透明度设置为 0.2(0 完全透明,1 完全不透明))# 添加一条红色的虚线,y 值为 0,用于显示负电价的参考线
  9. plt.axhline(
  10. y=0,# y 轴的值为 0
  11. color="red",# 虚线的颜色为红色
  12. linestyle="--"# 虚线的线型为虚线)# 设置 x 轴刻度标签的旋转角度为 45 度,并且水平对齐方式为右对齐
  13. plt.setp(
  14. ax.get_xticklabels(),# 获取 x 轴刻度标签
  15. rotation=45,# 设置标签的旋转角度为 45
  16. ha='right'# 设置标签的水平对齐方式为右对齐)# 设置图形的标题
  17. plt.title("一段比较典型的负电价趋势:2022年5月1日 - 2022年5月9日")

回显

在这里插入图片描述

2022年1月28日 - 2022年2月6日 电价 线图
代码

  1. plt.figure(figsize=(20,8))
  2. ax = sns.lineplot(electricity_price.loc["2023-01-21":"2023-02-02"]["price"], color="black")
  3. plt.axhline(y=0, color="red", linestyle="--")
  4. plt.setp(ax.get_xticklabels(), rotation=45, ha='right')
  5. plt.title("假期对负电价的影响 2022年1月28日 - 2022年2月6日")

回显

在这里插入图片描述

5 高电价形成原因分析

鼠标右键 -> 在新标签页中打开图像
在这里插入图片描述
高电价频数 出现的小时分布
代码

  1. # 计算电价的上限阈值,使用 3 标准差原则来检测异常值
  2. upper_threshold =(
  3. electricity_price["price"].mean()+# 电价的均值3* electricity_price["price"].std()# 加上 3 倍的电价标准差)# 创建一个布尔型掩码,用于标识电价高于上限阈值的异常值
  4. high_abnormal_mask =(
  5. electricity_price["price"]> upper_threshold # 判断电价是否大于计算得到的上限阈值)
  1. plt.figure(figsize=(12,7))
  2. ax = sns.countplot(electricity_price[high_abnormal_mask], x="hour")
  3. ax.set(title="高电量频数出现的小时分布")

回显

在这里插入图片描述

高电价频数 出现的月分布
代码

  1. plt.figure(figsize=(12,7))
  2. ax=sns.countplot(electricity_price[high_abnormal_mask],x="month")
  3. ax.set(title="高电量频数出现的月分布");

回显

在这里插入图片描述

高电价频数 出现的日期排序数表
代码

  1. # 从电价数据中筛选出高于上限阈值的异常值(
  2. electricity_price[high_abnormal_mask]# 按月份和日期分组,并计算每个组合的异常值记录数量.groupby(["month","day"]).size()# 计算每个分组的大小(即每个分组的记录数).reset_index(name="count")# 重置索引,将分组字段转换为 DataFrame 的列.sort_values("count",# "price" 列排序
  3. ascending=False)# 降序排序.head(15)# 选择排序后的前 15 行)

回显

在这里插入图片描述

2022年8月1日 - 2022年8月8日 总需求 线图
代码

  1. plt.figure(figsize=(20,8))
  2. ax = sns.lineplot(electricity_price.loc["2022-08-01":"2022-08-08"]["demand"], color="black")
  3. plt.setp(ax.get_xticklabels(), rotation=45, ha='right')
  4. plt.axvspan("2022-08-03","2022-08-06", color="yellow", alpha=0.2)
  5. plt.title("2022年8月1日 - 2022年8月8日 总需求")

回显

在这里插入图片描述

2022年8月1日 - 2022年8月8日 电价 线图
代码

  1. plt.figure(figsize=(20,8))
  2. ax = sns.lineplot(electricity_price.loc["2022-08-01":"2022-08-08"]["price"], color="black")
  3. plt.axhline(y=upper_threshold, color="red", linestyle="--")
  4. plt.setp(ax.get_xticklabels(), rotation=45, ha='right')
  5. plt.title("典型高电价时间段 2022年8月1日 - 2022年8月8日 中的3-6日")

回显

在这里插入图片描述

6 双变量分析

鼠标右键 -> 在新标签页中打开图像
在这里插入图片描述
pandas 库 编程实现 皮尔逊相关系数(r)
代码

  1. electricity_price[["demand","price"]].corr()

回显

在这里插入图片描述

numpy 库 编程实现 皮尔逊相关系数(r)
代码

  1. import numpy as np
  2. ar_1=electricity_price[train_mask][["demand"]].values
  3. ar_2=electricity_price[train_mask][["price"]].values
  4. np.corrcoef(np.column_stack((ar_1, ar_2)).T)

回显

在这里插入图片描述

回归图(散点图及拟合线)
代码

  1. # 创建一个图形,大小为 8x10 英寸
  2. plt.figure(figsize=(8,10))# 绘制回归图(散点图及拟合线)
  3. sns.regplot(
  4. data=electricity_price.loc["2022"],# 选择2022年的数据
  5. x="demand",# x 轴的变量为 "demand"
  6. y="price",# y 轴的变量为 "price"
  7. scatter_kws={# 设置散点图的样式"s":0.5,# 散点的大小设置为 0.5"alpha":0.6,# 散点的透明度设置为 0.6"color":"black"# 散点的颜色设置为黑色},
  8. color="red",# 拟合线的颜色设置为红色
  9. lowess=True# 启用局部加权回归(Lowess)以拟合数据)

回显

在这里插入图片描述

EDA 总结

在这里插入图片描述

Read more


本文转载自: https://blog.csdn.net/sk8Love956/article/details/140834330
版权归原作者 机动人心 所有, 如有侵权,请联系我们删除。

“Datawhale AI 夏令营 市场博弈和价格预测 EDA 探索性数据分析”的评论:

还没有评论