多日期结算周期机组发电量模拟函数故障:输出重复需修正
解决分日期分结算周期的机组发电量模拟结果重复问题
问题核心
基于merit_order(机组优先级)、total_fossil_demand(多日期分结算周期的化石燃料需求)、Max_cumulative_generation(按优先级累积的机组最大发电量上限)三个Pandas DataFrame开发的模拟函数,目前所有日期的发电量输出完全重复,无法实现按日期+结算周期维度的独立计算。
问题根源
函数未针对日期+结算周期的组合维度做分组处理,而是全局套用同一套计算逻辑,导致所有日期复用了同一周期的计算结果。
解决方案:按分组维度重构计算逻辑
通过groupby(['日期', '结算周期'])对数据做分组,让每个分组独立执行发电量分配规则,确保不同日期、不同结算周期的结果互不干扰。
步骤1:核心单周期计算函数
先实现针对单个(日期+结算周期)分组的发电量计算逻辑:
import pandas as pd def calculate_single_period_dispatch(demand_series, period_merit_order, period_max_cumulative): """ 计算单个日期+结算周期的机组发电量 参数: demand_series: 单周期的化石燃料需求(带(日期,结算周期)索引的Series) period_merit_order: 当前结算周期的机组优先级DataFrame period_max_cumulative: 当前日期+结算周期的累积发电量上限DataFrame 返回: 该周期的各机组发电量DataFrame """ # 按优先级排序机组(确保和merit_order定义一致) sorted_units = period_merit_order.sort_values("优先级", ascending=True).reset_index(drop=True) remaining_demand = demand_series["total_fossil_demand"] dispatch_records = [] current_date, current_period = demand_series.name for _, unit in sorted_units.iterrows(): unit_id = unit["机组ID"] unit_max_gen = unit["单机最大发电量"] # 获取该机组当前周期的累积发电量上限 cum_max = period_max_cumulative.loc[ period_max_cumulative["机组ID"] == unit_id, "Max_cumulative_generation" ].values[0] # 分配发电量:取剩余需求、单机上限、累积上限三者最小值 gen_amount = min(remaining_demand, unit_max_gen, cum_max) dispatch_records.append({ "日期": current_date, "结算周期": current_period, "机组ID": unit_id, "发电量": gen_amount }) remaining_demand -= gen_amount # 需求耗尽时,剩余机组发电量设为0 if remaining_demand <= 0: remaining_units = sorted_units.iloc[_+1:] for _, ru in remaining_units.iterrows(): dispatch_records.append({ "日期": current_date, "结算周期": current_period, "机组ID": ru["机组ID"], "发电量": 0 }) break return pd.DataFrame(dispatch_records)
步骤2:分组调用主函数
遍历所有(日期+结算周期)分组,调用核心函数计算并合并结果:
def simulate_full_dispatch(total_fossil_demand, merit_order, max_cumulative_generation): """ 全量模拟分日期分结算周期的机组发电量 参数: total_fossil_demand: 含日期、结算周期、total_fossil_demand字段的DataFrame merit_order: 含结算周期、机组ID、优先级、单机最大发电量字段的DataFrame max_cumulative_generation: 含日期、结算周期、机组ID、Max_cumulative_generation字段的DataFrame 返回: 分日期分结算周期的各机组发电量结果DataFrame """ # 按日期+结算周期分组处理需求数据 grouped_demand = total_fossil_demand.groupby(["日期", "结算周期"]) all_results = [] for group_key, demand_group in grouped_demand: current_date, current_period = group_key # 筛选当前结算周期的机组优先级数据 period_merit = merit_order[merit_order["结算周期"] == current_period] # 筛选当前日期+结算周期的累积发电量上限数据 period_cum_max = max_cumulative_generation[ (max_cumulative_generation["日期"] == current_date) & (max_cumulative_generation["结算周期"] == current_period) ] # 计算该分组的发电量 period_result = calculate_single_period_dispatch(demand_group.squeeze(), period_merit, period_cum_max) all_results.append(period_result) # 合并所有分组结果 final_result = pd.concat(all_results, ignore_index=True) return final_result
验证与期望输出
调用simulate_full_dispatch后,将得到分日期分结算周期的独立结果,示例如下:
| 日期 | 结算周期 | 机组ID | 发电量 |
|---|---|---|---|
| 2024-01-01 | 1 | UC1 | 100 |
| 2024-01-01 | 1 | UC2 | 80 |
| 2024-01-01 | 2 | UC1 | 120 |
| 2024-01-02 | 1 | UC1 | 90 |
| 2024-01-02 | 1 | UC2 | 75 |
注意事项
- 确保三个输入DataFrame的字段名与代码中使用的一致,若有差异需对应调整
- 若
merit_order的优先级规则是全局而非分结算周期,可去掉代码中对结算周期的筛选 - 若存在需求为0的情况,需在函数中添加判断,直接返回所有机组发电量为0的结果
内容的提问来源于stack exchange,提问作者Chetan Patel
相关产品推荐
相关产品推荐

