3、Python数据处理:Pandas库入门、DataFrame操作、时间序列数据处理

说实话,做储能运维数据可视化,最绕不开的就是Pandas。我刚开始接触这个库的时候,觉得它就是个“高级Excel”。但真正用起来才发现——它比Excel强太多了。尤其是处理时间序列数据,简直是量身定做。

这一章,我就带你快速上手Pandas。咱们不讲虚的,直接上干货。

3.1 Pandas库入门:为什么是它?

Pandas是Python里最流行的数据处理库。没有之一。它的核心就两个东西:Series(一维数据)和DataFrame(二维表格)。

你想想看,储能运维数据长什么样?

  • 电池电压、电流、温度——这些是数值列
  • 采集时间——这是时间列
  • 设备编号——这是分类列

这不就是一张典型的表格吗?Pandas就是专门处理这种数据的。

核心概念:

  • Series:带标签的一维数组,类似Excel里的一列
  • DataFrame:带标签的二维表格,类似整个Sheet
  • Index:行标签,可以是数字、时间戳、字符串

我个人习惯,拿到任何数据第一步就是转成DataFrame。因为后续的筛选、聚合、绘图,全都基于它。

3.2 DataFrame操作:增删改查,一个都不能少

DataFrame的操作,说白了就四类:读、选、改、存。咱们一个一个来。

3.2.1 创建DataFrame

最常见的方式是从CSV文件读取。我在项目中遇到过,有些运维数据是Excel格式的,但CSV更轻量,我建议优先用CSV。

import pandas as pd

# 从CSV读取
df = pd.read_csv('battery_data.csv')

# 或者手动创建
data = {
    'time': ['2024-01-01 00:00', '2024-01-01 00:05', '2024-01-01 00:10'],
    'voltage': [3.7, 3.69, 3.68],
    'current': [10.2, 10.1, 9.9],
    'soc': [85.0, 84.5, 84.0]
}
df = pd.DataFrame(data)
print(df.head())  # 看前5行

3.2.2 数据筛选与切片

筛选数据是日常操作。嗯,这里要注意:Pandas的索引方式有两种,lociloc。前者按标签,后者按位置。

# 按条件筛选——找出电压低于3.6V的异常数据
abnormal = df[df['voltage'] < 3.6]

# 按列名选取
voltages = df['voltage']

# 按行列位置选取
first_three_rows = df.iloc[0:3, :]

避坑指南:我曾经在筛选时直接用df[df.voltage < 3.6],结果列名带空格就报错了。后来我统一用df['列名']这种写法,稳得很。

3.2.3 数据清洗

真实数据永远不干净。缺失值、重复值、异常值,这三座大山你迟早要翻。

# 检查缺失值
print(df.isnull().sum())

# 填充缺失值——我一般用前向填充,适合时间序列
df.fillna(method='ffill', inplace=True)

# 删除重复行
df.drop_duplicates(inplace=True)

# 删除全为空的行
df.dropna(how='all', inplace=True)

警告:千万别一上来就dropna()删掉所有含空值的行。储能数据里,偶尔缺失一两个采样点很正常。删多了,时间序列就不连续了。我建议先用ffillinterpolate

3.3 时间序列数据处理:储能运维的核心

储能数据最显著的特征是什么?时间。电压随时间波动,SOC随时间变化,充放电事件按时间发生。所以,时间序列处理是重中之重。

3.3.1 时间索引的设定

第一步,把时间列转成Pandas的datetime类型,并设为索引。

# 转换时间列
df['time'] = pd.to_datetime(df['time'])

# 设为索引
df.set_index('time', inplace=True)

# 现在你可以按时间切片了
morning_data = df['2024-01-01 00:00':'2024-01-01 06:00']

为什么一定要设成索引?因为Pandas对时间索引有大量优化。你想想看,按小时、按天、按月聚合,这些操作在时间索引下就是一行代码的事。

3.3.2 重采样——从秒级到小时级

储能系统的采集频率通常很高,比如每5秒一条。但做趋势分析时,你不需要这么密。重采样就是降频。

# 按小时取平均
hourly_avg = df.resample('H').mean()

# 按天取最大值
daily_max = df.resample('D').max()

# 按15分钟取中位数
quarterly_median = df.resample('15T').median()

经验之谈:我在做电池健康度分析时,发现用resample('D').mean()会丢失充放电的峰值信息。后来我改成同时计算均值、最大值、最小值,三列一起看,效果就好多了。

3.3.3 时间偏移与滑动窗口

滑动窗口在储能里太常用了。比如计算过去1小时的电压标准差,判断数据是否异常。

# 7点滑动平均——平滑曲线
df['voltage_smooth'] = df['voltage'].rolling(window=7).mean()

# 计算过去1小时的电压波动
df['voltage_std_1h'] = df['voltage'].rolling('1H').std()

# 时间偏移——比如对比今天和昨天的同一时刻
df['voltage_yesterday'] = df['voltage'].shift(288)  # 假设5秒一条,一天28800条

为什么会用到滑动窗口?因为电池的电压波动往往不是瞬间的,而是渐变的。滑动窗口能帮你捕捉这种趋势,过滤掉噪声。

3.3.4 时间特征提取

有时候,你需要从时间戳里提取“小时”、“星期几”、“是否节假日”等特征。这些对分析充放电行为很有用。

# 提取时间特征
df['hour'] = df.index.hour
df['day_of_week'] = df.index.dayofweek  # 0=周一
df['is_weekend'] = df['day_of_week'].isin([5, 6]).astype(int)

# 看看不同时段的平均SOC
hourly_soc = df.groupby('hour')['soc'].mean()

小技巧:我习惯把时间特征单独存一列,方便后续做机器学习。比如预测SOC时,“小时”和“星期几”就是很好的特征。

3.4 知识体系总览

下面这张图,是我梳理的本章知识结构。你可以把它当成一张地图,随时回来对照。

Pandas数据处理知识体系 Pandas数据处理 Pandas库入门 Series & DataFrame CSV/Excel读写 DataFrame操作 筛选切片 数据清洗 聚合分组 时间序列处理 时间索引设定 重采样(resample) 滑动窗口(rolling) 时间特征提取 目标:高效处理储能运维时序数据

3.5 实战小贴士

最后,分享几个我在项目中踩过的坑,希望能帮你少走弯路。

场景 推荐做法 不推荐做法
读取大文件(>1GB) chunksize分块读取 一次性read_csv(),内存爆掉
处理缺失值 ffill,再interpolate 直接dropna(),破坏时间连续性
时间索引 统一设为UTC,避免时区问题 混用本地时间和UTC
重采样频率 根据业务需求选(如15分钟) 盲目用1秒,数据量太大

嗯,这一章的内容就到这里。Pandas这东西,光看是学不会的。我建议你打开Jupyter Notebook,把上面的代码敲一遍。尤其是时间序列那部分,多试试不同的重采样频率,看看数据怎么变。动手之后,你才能真正理解它的威力。


公众号:蓝海资料掘金营,微信deep3321