用Pandas resample基于充电起止时间计算电动车充电平均能耗的方法
核心实现思路
首先明确两个容易混淆的计算目标,对应不同的实现逻辑,匹配你已有的pandas resample使用经验:
场景1:为每条充电记录生成单条维度的平均能耗列
这个场景不需要用到resample,核心逻辑是用单条充电的总能耗除以对应充电时长,直接计算即可:
- 先完成基础数据格式转换:
import pandas as pd # 读取原始充电数据集 df = pd.read_csv("your_ev_charge_dataset.csv") # 按给定的Y/m/d H:M:S格式转换时间字段为pandas时序类型 df["start_time"] = pd.to_datetime(df["start_time"], format="%Y/%m/%d %H:%M:%S") df["end_time"] = pd.to_datetime(df["end_time"], format="%Y/%m/%d %H:%M:%S") # 计算单条充电的总时长,单位为小时 df["charge_duration_h"] = (df["end_time"] - df["start_time"]).dt.total_seconds() / 3600 - 计算单条记录的平均功率(即充电过程的平均能耗速率):
df["avg_power_kw"] = df["energy (kwh)"] / df["charge_duration_h"]
场景2:结合resample实现跨时间区间的时序粒度平均能耗计算
这是你之前用单点时间戳做resample平均没有覆盖的场景:原始充电记录是从start_time到end_time的连续区间,很可能跨多个固定时间桶(比如一次充电从23:40持续到次日00:30,会跨1小时粒度的两个时间桶),如果直接按start_time做resample切分,会把整条记录的能耗算到开始时间所属的桶里,造成统计偏差。
对应的实现步骤为:
- 定义需要聚合的时间粒度(比如按1小时、1天),生成覆盖全部充电时段的连续时间轴作为切分桶
- 对每条跨区间的充电记录,计算它和每个时间桶的重叠时长,按重叠时长的比例分摊这条记录的总能耗
- 把拆分后的所有片段按时间索引对齐,再用熟悉的
resample做聚合计算平均能耗
# 定义聚合粒度,可根据需求替换为"D"(天)、"30T"(半小时)等 resample_step = "1H" # 生成覆盖全量数据范围的连续时间桶 time_bins = pd.date_range( start=df["start_time"].min().floor(resample_step), end=df["end_time"].max().ceil(resample_step), freq=resample_step ) # 拆分每条跨区间的充电记录,生成按时间桶分摊的细分片段 split_fragments = [] for _, row in df.iterrows(): # 找到当前充电记录覆盖的所有时间桶 covered_bins = time_bins[ (time_bins >= row["start_time"].floor(resample_step)) & (time_bins <= row["end_time"].ceil(resample_step)) ] for bin_start in covered_bins: # 计算充电时段和当前时间桶的实际重叠区间 seg_start = max(row["start_time"], bin_start) seg_end = min(row["end_time"], bin_start + pd.Timedelta(resample_step)) overlap_hour = (seg_end - seg_start).total_seconds() / 3600 if overlap_hour <= 0: continue # 按时长比例分摊总能耗到当前时间桶 allocated_energy = row["energy (kwh)"] * (overlap_hour / row["charge_duration_h"]) split_fragments.append({ "time_bin": bin_start, "allocated_energy": allocated_energy, "overlap_hour": overlap_hour }) # 转换为带时间索引的DataFrame,用resample聚合得到时序平均能耗 split_df = pd.DataFrame(split_fragments).set_index("time_bin") time_agg_result = split_df.resample(resample_step).agg( total_kwh=("allocated_energy", "sum"), total_charge_hour=("overlap_hour", "sum"), # 时序维度的平均能耗(平均充电功率,单位kW) avg_power_kw=("allocated_energy", lambda s: s.sum() / split_df.loc[s.index, "overlap_hour"].sum()) )
注意事项
- 如果数据量达到百万条以上,逐行循环拆分的效率偏低,可以改用
pd.Interval的区间匹配逻辑优化拆分速度,核心逻辑保持不变 - 拆分分摊的规则可以根据需求调整(比如只要充电时长占单桶的比例超过阈值就算入桶),不影响后续resample的聚合流程
内容的提问来源于stack exchange,提问作者dani.dot
相关产品推荐
相关产品推荐

