task1
数据:
electricity price.csv时间两列合并后得electricity_price_parsed.csv
是描述电力需求(demand)与市场出清价格(clearing price (CNY/MWh))随时间的变化数据
电力需求每15min变动一次,市场出清价格每1h变动一次,用前100条数据稍微确认一下。由图可验证需求上升导致价格上升的规律。
unit.csv 发电机组,即供给方数据,task1中只利用coal consumption一列作为成本参数
电力市场交易机制:
已知某一时刻电力需求,按所有机组报价从低到高排序,依次接受报价,直到累计装机量超过需求量。最后一个满足需求的发电机组,即第一个使累计装机量不小于需求量的发电机组,其所报价为市场出清价格。
报价机制:
按边际成本报价。用每度电所耗煤估计边际成本。估计方法采用线性回归。
代码实现:
先将unit.csv数据按近似边际成本coal consumption从低到高排序,再计算累计装机量cumulative_capacity;
遍历电力需求 ,找到对应“报价”:每度电所耗煤炭。并将这个列表加入electricity_price中
unit=pd.read_csv('data/unit.csv')
sorted_unit=unit.sort_values('coal consumption (g coal/KWh)')
sorted_unit['cumulative_capacity']=sorted_unit['Capacity(MW)'].cumsum()
costs=[]
for demand in electricity_price['demand']:
cost= sorted_unit[sorted_unit['cumulative_capacity'] >= demand]["coal consumption (g coal/KWh)"].iloc[0]
costs.append(cost)
electricity_price['highest_cost']=costs
市场出清价格 与 前述所得边际煤炭消耗 的散点图与线性拟合结果:
问题:
- 报价不止和边际成本有关。在需求高的时候,倾向于报高价;需求量小到一定程度可能会亏本卖出。
- 边际成本不止与每度电所耗煤炭有关
- 一开始不是边际收益等于边际成本的市场均衡状态
task2数据探索
对于electricity_price_parsed.csv
正好缺失值都在表后面
pandas技巧:读入数据时设置timestamp为索引,用parse_dates=['timestamp']方便时序特征构建,还可以用loc挑出一天各小时的数据
electricity_price = pd.read_csv(base_path/"electricity_price_parsed.csv", parse_dates=["timestamp"], index_col=0)
统计指标分析:
- demand近似正态分布
- clearing price发现异常数据:负价、低价、高价
时间序列特征构建
# 从 DataFrame 的索引中提取时间信息,并添加为新的列
# 假设索引为 DatetimeIndex 类型
# 提取小时信息,并创建一个新列 "hour"
electricity_price["hour"] = electricity_price.index.hour
# 提取月份信息,并创建一个新列 "month"
electricity_price["month"] = electricity_price.index.month
# 提取日期信息,并创建一个新列 "day"
electricity_price["day"] = electricity_price.index.day
# 提取星期几的信息(0 = 周一, 6 = 周日),并创建一个新列 "weekday"
electricity_price["weekday"] = electricity_price.index.weekday
# 提取年份信息,并创建一个新列 "year"
electricity_price["year"] = electricity_price.index.year
从而可以对不同时间段进行分组:
1. 通过groupby按小时和年份分组,统计电价、总负荷均值并可视化,发现
- 这些年电价和总负荷的变化走势大体一致,傍晚最高、中午最低
- 2021年电价波动最明显、各小时总负荷最高
- 2021-2024年电力需求总体呈下降趋势
2. 通过透视表pivot_table按小时和月份分组,统计电价均值(默认)并可视化,发现
普遍在下午3点以后电价较高,上午8点到下午3点电价最低。
由1、2可构建二分类变量:是否处于傍晚或正午时段,然后是不是该把原来的hour列删掉?
noon_start = 10
noon_end = 15
evening_start = 16
evening_end = 21
def assign_time_of_day(hour):
if noon_start <= hour <= noon_end:
return 'Noon'
elif evening_start <= hour <= evening_end:
return 'Evening'
else:
return 'Other'
electricity_price['time_of_day'] = electricity_price['hour'].apply(assign_time_of_day)
异常值探索
负电价产生规律
3. 统计负电价频数出现的小时分布,发现
中午最常出现负电价交易,可能因为此时需求量经常很少
4. 统计负电价频数出现的月分布,发现
前两季度较后两季度更容易出现负电价
5. 统计负电价出现最多的日期
五月、二月、四月有较多天排在前十五,比如第一行意思是三年来的5月2日出现了88次负价格?
(
# 选择满足 minus_mask 条件的数据(minus_mask=electricity_price['price']<0))
electricity_price[minus_mask]
# 按月份和日期分组,计算每个组合的记录数量
.groupby(["month", "day"])["price"]
.size() # 计算每个分组的大小(即每个分组的记录数)
.reset_index() # 重置索引,使 groupby 结果成为 DataFrame,并保留分组字段为列
.sort_values("price", # 按 "price" 列排序
ascending=False) # 降序排序
.head(15) # 选择排序后的前 15 行
)
看来5.2 5.1 5.6负电价交易多,据此以及负电价多出现在中午的规律绘制一段比较典型的负电价趋势。1、2月电价也多出现负数,推测和春节有关。
或许负电价格交易增多和放假公司用电需求减少有关。对比一下另一几乎没有负值出现的时段
高电价产生规律
超过均值三倍标准差的电价考虑为高电价
6. 统计高电价频数出现的小时分布,发现
傍晚最常出现高电价交易,可能因为此时需求量经常很多
7. 统计高电价频数出现的月分布,发现
- 8月份频数最高
- 6,7,9,10,11月份无高电价
8. 统计高电价出现最多的日期,前几个都在八月
9. 直接看市场出清价格和需求的相关性
先跑一遍时间序列预测
ep_encoded添加了一些特征?
划分出验证集验证模型效果
在添加highest_cost后把demand列删掉了,因为这样在验证集上误差更小
不需要脑子的流程:
train_test=ep_encoded[~ep_encoded['price'].isna()]
y=train_test.price
X=train_test.drop('price',axis=1)
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)
model=RandomForestRegressor()
model.fit(X_train,y_train)
y_pred=model.predict(X_test)
mse=mean_squared_error(y_test,y_pred)
print(mse)
test=ep_encoded[ep_encoded['price'].isna()]
X_test=test.drop('price',axis=1)
y_pred=model.predict(X_test)
submit=pd.read_csv('data/sample_submit.csv')
submit['clearing price (CNY/MWh)']=y_pred
submit.to_csv('submit2.csv',index=False)
(验证集上3200+的mse)
结果误差反而能跑到两万orz。。。没点的灰线是预测结果。
问题:
2024电价应该总体比前三年低
不会特征工程。。。
以及还没看
ABM构建
推测供电方行为规律:
先复读教程再想怎么建模orz