第二章:数据加载与初步探索
好,咱们正式开始动手了。
上一章聊了聊电价预测的背景和坑,这一章咱们直接上代码。我个人习惯,拿到任何数据源,第一件事不是建模,而是先把它请进Python里,好好打量一番。说白了,就是先看看这堆数据长什么样,有没有缺胳膊少腿。
2.1 用Pandas加载CSV文件
CSV文件是电价数据最常见的格式。电力调度中心、交易中心给的数据,十有八九是CSV。我建议你直接用pd.read_csv(),简单粗暴。
import pandas as pd
# 加载电价数据
df = pd.read_csv('electricity_price.csv')
嗯,这里要注意。我在项目中遇到过,有些CSV文件编码不是UTF-8,而是GBK或者GB2312。尤其是国内一些老系统导出的数据,一读就报错。这时候加个参数就行:
df = pd.read_csv('electricity_price.csv', encoding='gbk')
如果还报错,试试encoding='gb2312'或者encoding='utf-8-sig'。你想想看,一个编码问题卡半天,多冤。
2.2 加载Excel文件
Excel文件也常见,尤其是报表类的数据。用pd.read_excel()搞定。
df = pd.read_excel('electricity_price.xlsx', sheet_name='Sheet1')
这里有个坑——Excel文件可能有多张表。我曾经拿到一个文件,里面藏着七八个sheet,每个sheet代表不同省份的电价。如果你不指定sheet_name,Pandas默认只读第一张。所以,先看看文件里有几张表:
xls = pd.ExcelFile('electricity_price.xlsx')
print(xls.sheet_names)
这样心里就有数了。
2.3 查看数据基本信息
数据加载进来后,别急着分析。先做三件事:head()、info()、describe()。这是我的老规矩。
2.3.1 head()——瞄一眼数据长啥样
print(df.head())
默认显示前5行。我习惯先看个10行:
print(df.head(10))
为什么?因为电价数据通常有时间列、价格列、可能还有负荷、温度等特征。看一眼列名和数值范围,心里就有底了。比如,价格列如果出现负数,那就要警惕了——是不是数据采集异常?
2.3.2 info()——摸清数据类型和缺失情况
print(df.info())
这个方法会告诉你:
- 总共有多少行、多少列
- 每列的数据类型(int64、float64、object等)
- 每列有多少个非空值
我个人最关注的是数据类型和缺失值。电价数据的时间列,经常被读成object类型,而不是datetime。这会导致后续时间序列分析出问题。还有,如果某列缺失值太多,比如超过30%,那这列基本可以放弃了。
重点:info()输出的非空值数量,如果小于总行数,说明有缺失值。缺失值处理是数据清洗的重头戏,后面章节会细讲。
2.3.3 describe()——看统计摘要
print(df.describe())
这个方法只对数值列有效。它会输出:
- count:非空值数量
- mean:平均值
- std:标准差
- min:最小值
- 25%、50%、75%:四分位数
- max:最大值
举个例子,如果电价的最小值是负数,或者最大值高得离谱(比如10000元/度),那数据肯定有问题。我在项目中遇到过,某天的电价突然飙到9999,后来发现是采集设备故障。这种异常值,必须处理掉。
2.4 数据类型概览
数据类型决定了你能对数据做什么操作。Pandas里常见的数据类型有:
| 类型 | 说明 | 常见场景 |
|---|---|---|
| int64 | 整数 | 年份、小时、负荷值 |
| float64 | 浮点数 | 电价、温度、风速 |
| object | 字符串/混合类型 | 时间戳(未转换前)、地区名 |
| datetime64 | 日期时间 | 时间索引(必须转换) |
| bool | 布尔值 | 节假日标志、异常标志 |
我建议你养成一个习惯:加载数据后,立刻检查时间列的类型。如果是object,马上转成datetime:
df['time'] = pd.to_datetime(df['time'])
为什么这么急?因为电价预测本质上是时间序列问题。时间列必须是datetime类型,你才能做重采样、滑动窗口、滞后特征等操作。否则,后面每一步都会卡住。
小技巧:如果时间列格式不标准,比如'2024-01-01 00:00:00',pd.to_datetime()通常能自动识别。但如果格式很奇葩,比如'2024/1/1 0:00',可以指定format参数:pd.to_datetime(df['time'], format='%Y/%m/%d %H:%M')。
2.5 知识体系一览
这一章的内容,说白了就是数据清洗的“入门仪式”。我画了张图,帮你理清逻辑:
这张图展示了咱们这一章的核心流程:从加载数据开始,到查看基本信息,再到检查数据类型。其中,时间列转换、缺失值检查、异常值检查是三个关键分支。后面的章节,咱们会逐一深入。
2.6 避坑指南
我曾经踩过的坑:
- 读CSV时没指定
encoding,结果中文列名全变成乱码。后来我养成了习惯,先问数据来源方“文件是什么编码”。 - 用
head()看了前5行,觉得数据挺干净,结果跑到后面发现大量缺失值。所以我现在一定会用info()检查全局。 - 时间列没转成datetime,直接做滑动窗口,结果报错。从那以后,我加载数据后的第一件事就是转时间列。
好了,这一章就到这里。数据加载和初步探索,是数据清洗的“敲门砖”。你把这些基础打牢了,后面的清洗工作才能顺风顺水。
我的习惯:每次拿到新数据,我都会写一个data_overview.py脚本,把head()、info()、describe()、时间列转换、缺失值统计全写进去。这样每次只需要改个文件名,就能快速了解数据全貌。你也可以试试。