☰
电池AI编程实战营系列之二:从CSV读懂电池循环数据,画出第一张容量衰减曲线(含清洗与离群点处理)
2026/10/19 1:59:02 网站建设 项目流程

拿到几百行电池循环数据,你第一步会做什么?

【A】直接画图 📈

【B】先清洗再动手 🧹

【C】先看字段说明 📋

  • 本系列第02篇培训教材:带你掌握电池数据工程的第一步—从 CSV 读懂循环测试数据、做清洗、画容量衰减曲线。
  • 本文将演示:①用 pandas 读取 CSV 并看懂字段;②处理缺失值与离群点;③计算 SOH 并绘制容量衰减曲线、识别 80% 寿命阈值。
  • 代码已在本环境实测运行,附复现环境卡与真实运行验证记录,可离线复现。
  • 核心观点:"垃圾进,垃圾出"——数据清洗的质量,直接决定后面所有 AI 模型的可靠性。


一、问题的起点:几百行循环数据,怎么下手?

上一篇你搭好了环境。现在面对真实问题:实验给了你几百次循环的放电容量数据,怎么直观看出电池衰减成什么样?

但现实中的原始数据从来不是干净的: - 有缺失值(某天设备断点,容量是空的) - 有离群点(传感器抖动、记录异常,出现离谱数值) - 有噪声(测量本身的随机波动)

如果不管这些直接画图、直接喂给模型,结果是:曲线恶心、模型被带偏。所以数据清洗不是可选项,是必选项。


二、读数据:pandas 一眼看清字段

用上一篇的"隔离环境",先读入数据并看一眼全貌(.shape、.head()、.info()):

import pandas as pd df = pd.read_csv('battery_cycle_data.csv') print("形状 shape:", df.shape) # (行数, 列数) print("前5行:\n", df.head()) print("数据类型与缺失:\n", df.info())

数据字段说明(本例为模拟,真实数据字段类似): -cycle:循环次数(第几次充放电) -capacity_ah:该次循环的放电容量(Ah),体检电池健康的关键指标-voltage_v:电压(V)

📌 真实工程常用NASA 电池老化数据集 / 牛津电池数据集。本篇为保证读者离线也能复现,用固定 seed 生成本地 CSV 演示流程;你完全可把read_csv换成真实数据路径,处理逻辑不变。


三、数据清洗:先治脏数据

这是本篇最值钱的 20 行代码。核心三步:处理缺失 → 处理离群 → 归一化。

import numpy as np df = pd.read_csv('battery_cycle_data.csv') # 1) 缺失值:前向填充(用上一个有效值补)+ 中位数兜底 if df['capacity_ah'].isna().any(): df['capacity_ah'] = df['capacity_ah'].ffill().fillna(df['capacity_ah'].median()) # 2) 离群点:超出 均值±3σ 的替换为中位数(简单稳健,适合教学) cap = df['capacity_ah'].copy() mean, std = cap.mean(), cap.std() mask = (cap < mean - 3*std) | (cap > mean + 3*std) print(f"检测到离群点 {mask.sum()} 个") cap[mask] = cap.median() df['capacity_ah'] = cap # 3) 归一化 SOH:= 当前容量 / 初始最大容量 df['soh'] = df['capacity_ah'] / df['capacity_ah'].max()

为什么这样处理?-缺失用 ffill:容量是连续物理量,用相邻值补比用均值合理。 -离群用 3σ 判定 + 中位数替换:3σ 之外的极值很可能是异常,中位数对离群稳健(不被离群本身拉偏)。 -SOH 归一化:把容量换算成 0~1 的健康度,统一不同电芯的对比尺度。


四、画图:容量衰减曲线 + 80% 寿命线

清洗完就能画能看懂的曲线了—并加上"80% 阈值"这条行业通用寿命红线(当 SOH ≤ 0.8 通常视为退役阈值):

import matplotlib.pyplot as plt fig, ax = plt.subplots(figsize=(9,5)) ax.plot(df['cycle'], df['soh'], lw=1.8, color='tab:blue', label='清洗后SOH') ax.axhline(0.8, color='red', ls='--', lw=1, label='80%寿命阈值') ax.set_xlabel('循环次数'); ax.set_ylabel('SOH') ax.set_title('电池容量衰减曲线(清洗后)') ax.legend(); ax.grid(alpha=0.3) fig.tight_layout(); fig.savefig('fig_article02_curve.png', dpi=120)

五、真实运行验证记录

以下为本脚本在测试环境的真实输出:

已生成 data/battery_cycle_data.csv, 行数 400 读取原始数据 shape: (400, 3) 检测到离群点 1 个(1 处) === 运行验证记录 === 清洗后 SOH 最小值: 0.7129 清洗后 SOH 最大值: 1.0 达到80%阈值时的循环次数: 282 清洗后空值数: 0

观察结论: - 400 次循环数据,清洗后无空值、离群点被处理; - SOH 从 1.0 衰减到 0.71,在第 282 个循环跌破 80% 阈值; - 这段"282 次循环到寿"的信息,是后续做 SOH 预测、寿命估计的监督标签——下一篇就教你把它做成可复用函数。


六、环境卡

依赖清单(锁版本)

python==3.13.15 numpy==2.4.6 pandas==3.0.5 matplotlib==3.11.0 jupyter

验证命令与预期

conda activate battery-ai python demo_02.py

预期:几秒跑完无报错,输出含"达到80%阈值时的循环次数: 282",并生成fig_article02_curve.png。

常见报错自查表

报错原因解法
FileNotFoundError数据文件路径不对把battery_cycle_data.csv和脚本放同一目录
KeyError: 'capacity_ah'列名不一致print(df.columns)核对实际列名
numpy.nan误报缺失未处理确保先跑缺失值清洗步骤
中文字体方块未配置字体按第01篇自查表加字体

七、练习

  1. 改衰减速率:把0.0007改成0.0010,看 80% 阈值提前到第几个循环。
  2. 刻意不清洗:注释掉离群点处理,观察曲线出现"毛刺",理解清洗的必要性。
  3. 换真实数据:下载任公开电池数据集,仅改read_csv路径,验证清洗画图流程是否通用。

验收标准:能独立讲出"缺失值/离群点/SOH"各自为什么这样处理;能画出带 80% 阈值的衰减曲线并读出到寿循环数。


八、Q&A

Q1:为什么用 3σ 判离群,会不会误删好数据?A:3σ 是常用经验值,对服从近似正态的容量数据较稳健。若担心误删,可改用分位数法(如 IQR)或先画分布图观察。教学选用 3σ 简单直观。

Q2:缺失值为什么用 ffill 而不是直接删掉那行?A:容量是随时间连续变化的物理量,删行会破坏序列结构的连续性(尤其后续要按顺序训练时序模型),ffill 用相邻值补更合理。

Q3:模拟数据和真实 NASA 数据差别大吗?A:模拟数据信号形态近似、便于离线复现;真实数据有更复杂的非线性衰减、容量回升等现象。本例演示的是通用处理流程,换真实数据逻辑不变。

Q4:SOH 一定要除以最大值吗?A:常见做法是除以额定容量或初始容量。教学用最大值归一化更稳健(避免初值离群影响)。工程上按电池厂商标定为准。

Q5:清洗会影响最终 SOH 预测精度吗?A:会,而且影响很大。脏数据会污染特征和标签。清洗得当通常能明显提升模型稳定性和可复现性。


九、下一篇预告

第03篇:把今天这段"清洗-画图"逻辑封装成可复用函数,用 AI 工具帮你批量处理几百个电芯的文件——告别复制粘贴,迈向工程化。


AI 工具使用心得

本篇用 AI 生成数据清洗(ffill + 3σ)的稳健写法、并设计"生成带脏数据的模拟CSV"来演示清洗前后的对比——让 AI 造了一个可用来教学的'脏数据样例',比自己手动造更高效、更贴近真实。效率点:写演示数据+清洗逻辑一次成型。踩坑:先想让缺失值np.nan参与运算报错,明确要先做 isna() 检查再处理。


代码声明:本文代码与数据均为培训教学示例,用于演示数据清洗与分析方法,仅供学习复现与上手练习;不构成任何生产级软件、BMS 算法或商业产品实现建议。用于真实电池管理系统或量产场景时须另行充分验证,作者不对因环境差异、误用或改编造成的后果负责。

本文为技术科普与工程编程教程,不构成任何投资、购买或商业决策建议。文中涉及的技术路线、代码实现与运行环境信息可能存在更新,请以原文、最新官方文档及厂商最新发布为准。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询