第二章:数据加载与初步探索

好,咱们正式开始动手了。

上一章聊了聊电价预测的背景和坑,这一章咱们直接上代码。我个人习惯,拿到任何数据源,第一件事不是建模,而是先把它请进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 知识体系一览

这一章的内容,说白了就是数据清洗的“入门仪式”。我画了张图,帮你理清逻辑:

数据加载与初步探索流程 加载数据 read_csv / read_excel 基本信息查看 head / info / describe 数据类型检查 dtypes / astype 时间列转换 pd.to_datetime() 缺失值检查 isnull().sum() 异常值检查

这张图展示了咱们这一章的核心流程:从加载数据开始,到查看基本信息,再到检查数据类型。其中,时间列转换、缺失值检查、异常值检查是三个关键分支。后面的章节,咱们会逐一深入。

2.6 避坑指南

我曾经踩过的坑:

  • 读CSV时没指定encoding,结果中文列名全变成乱码。后来我养成了习惯,先问数据来源方“文件是什么编码”。
  • head()看了前5行,觉得数据挺干净,结果跑到后面发现大量缺失值。所以我现在一定会用info()检查全局。
  • 时间列没转成datetime,直接做滑动窗口,结果报错。从那以后,我加载数据后的第一件事就是转时间列。

好了,这一章就到这里。数据加载和初步探索,是数据清洗的“敲门砖”。你把这些基础打牢了,后面的清洗工作才能顺风顺水。

我的习惯:每次拿到新数据,我都会写一个data_overview.py脚本,把head()info()describe()、时间列转换、缺失值统计全写进去。这样每次只需要改个文件名,就能快速了解数据全貌。你也可以试试。

专注资料整理