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

Pandas根据值升降提取DataFrame首个充放电周期行数据

解决方案

核心逻辑是先标记每个数据点的充放电趋势,平段自动归属到相邻的同周期段,再通过连续段分组直接定位目标周期,完全不受初始数据状态影响,同时兼容重复时间索引、充放电中间夹带平台段的场景。


步骤说明

  • 计算SoC列逐点差分,标记三类趋势:差值为正属于充电上升、差值为负属于放电下降、差值为0属于平台暂留
  • 对趋势做双向填充:平台段优先继承前序趋势,开头无参考的初始平台段继承后续第一个有效趋势
  • 对连续相同趋势的段做分组,每个分组对应一个完整的充/放电子段
  • 筛选第一个充电分组得到首个充电周期,再筛选充电段之后的第一个放电分组得到首个放电周期

实现代码

import pandas as pd

# 标记SoC变化趋势:1=充电,-1=放电,0=平台
soc_diff = df["SoC"].diff()
trend = pd.Series(0, index=df.index, dtype=int)
trend[soc_diff > 0] = 1
trend[soc_diff < 0] = -1

# 填充趋势:平台段继承前序趋势,初始开头平台继承后续第一个有效趋势
trend = trend.ffill().bfill()

# 为连续相同趋势的段分配唯一分组ID
segment_id = (trend != trend.shift()).cumsum()

# 遍历整理所有连续段的位置信息
segments = []
for sid, group in df.groupby(segment_id):
    seg_trend = trend.loc[group.index[0]]
    segments.append({
        "trend": seg_trend,
        "start_iloc": df.index.get_loc(group.index[0]),
        "end_iloc": df.index.get_loc(group.index[-1])
    })

# 提取首个充电周期
first_charge = next(seg for seg in segments if seg["trend"] == 1)
df_charging = df.iloc[first_charge["start_iloc"] : first_charge["end_iloc"] + 1]

# 提取首个充电周期之后的第一个放电周期
first_discharge = next(seg for seg in segments if seg["trend"] == -1 and seg["start_iloc"] > first_charge["start_iloc"])
df_discharging = df.iloc[first_discharge["start_iloc"] : first_discharge["end_iloc"] + 1]

边界说明

  • 代码使用整数位置iloc做切片,即使存在重复时间索引也不会出现切片错误
  • 如果数据集全程没有充电/放电趋势,上述代码会触发StopIteration异常,可根据业务需求增加前置判断做异常处理
  • 充放电过程中任意长度的恒定值平台段都会被自动归属到对应周期,不需要额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:21:18