第4章:CSV数据读取与初步探索

各位同学,欢迎来到实战环节。从这一章开始,我们就要真刀真枪地跟风机SCADA数据打交道了。

我个人习惯,拿到任何数据源,第一件事不是建模,也不是画图。而是先把它读进来,然后好好“打量”一番。说白了,就像你拿到一本新书,先看看封面、目录、厚度,心里有个底。数据分析也是这个理儿。

4.1 用Pandas读取CSV文件

风机SCADA数据最常见的存储格式就是CSV。为什么?因为它简单、通用,几乎所有系统都能导出。我见过有些风场用Excel存数据,那真是噩梦——文件大一点就卡死,还容易损坏。

读取CSV,Pandas提供了read_csv()函数。这是最基础,也是最核心的一步。

import pandas as pd

# 读取SCADA数据
df = pd.read_csv('wind_turbine_scada.csv')

嗯,就这么一行。但这里有个坑——编码问题。我曾经在某个风场项目里,读一个国产机组的CSV文件,直接报错。后来发现是编码格式不是默认的UTF-8,而是GBK。所以,我建议你养成习惯,遇到中文数据,加上encoding='gbk'encoding='utf-8'参数。

小技巧:如果不知道文件编码,可以用记事本打开CSV文件,另存为时就能看到当前编码。或者用Python的chardet库自动检测。
# 带编码参数的读取方式
df = pd.read_csv('wind_turbine_scada.csv', encoding='gbk')

4.2 快速预览数据:head()方法

数据读进来了,第一件事是什么?看一眼长什么样。用head()方法,默认显示前5行。

# 查看前5行数据
df.head()

你会看到类似这样的表格:

时间戳 风速(m/s) 有功功率(kW) 桨距角(°) 发电机转速(rpm)
2024-01-01 00:00:00 8.5 1500.2 12.3 1750
2024-01-01 00:10:00 9.1 1620.5 11.8 1780
2024-01-01 00:20:00 7.8 1380.0 13.5 1700

看到这个,你心里就有数了:数据是10分钟一条的时序记录,包含风速、功率、桨距角、转速等关键参数。如果数据量很大,你也可以指定行数,比如df.head(10)看前10行。

4.3 数据概览:info()方法

head()只能看数据内容,但数据的“体质”怎么样?有没有空值?每列是什么类型?这时候就要用info()了。

# 查看数据基本信息
df.info()

输出结果大概长这样:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 52560 entries, 0 to 52559
Data columns (total 8 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   时间戳         52560 non-null  object 
 1   风速(m/s)     52560 non-null  float64
 2   有功功率(kW)  52560 non-null  float64
 3   桨距角(°)     52560 non-null  float64
 4   发电机转速(rpm) 52560 non-null  float64
 5   机舱温度(℃)   52300 non-null  float64
 6   齿轮箱油温(℃)  52180 non-null  float64
 7   状态码         52560 non-null  int64  
dtypes: float64(6), int64(1), object(1)
memory usage: 3.2 MB

这里信息量很大,我带你逐条看:

  • 行数:52560行,正好是一年(365天×24小时×6条/小时)的10分钟数据。
  • 列数:8列,包含时间、风速、功率等。
  • 非空计数:注意看“机舱温度”和“齿轮箱油温”这两列,非空值少于总行数。这说明什么?有缺失值
  • 数据类型:大部分是float64(浮点数),状态码是int64(整数),时间戳是object(字符串)。
注意:时间戳列显示为object类型,说明它还没被解析成时间格式。后面我们会专门讲如何处理时间序列数据。如果你现在就想处理,可以加parse_dates=['时间戳']参数。

4.4 统计描述:describe()方法

info()告诉你数据“有没有”,describe()则告诉你数据“好不好”。它会自动计算数值型列的统计量。

# 查看数值列的统计描述
df.describe()

输出结果:

统计量 风速(m/s) 有功功率(kW) 桨距角(°) 发电机转速(rpm)
count 52560.0 52560.0 52560.0 52560.0
mean 7.2 1200.5 10.8 1650.0
std 3.5 600.2 5.2 200.0
min 0.0 -50.0 0.0 0.0
25% 4.5 650.0 6.5 1500.0
50% 7.0 1150.0 10.0 1680.0
75% 9.8 1750.0 14.5 1820.0
max 25.0 2000.0 90.0 2000.0

这里有几个点值得关注:

  • 有功功率最小值是-50kW:这不对劲。风机正常发电不会为负值,除非是停机状态下的厂用电消耗。这说明数据里混入了异常值。
  • 桨距角最大值90°:正常运行时桨距角一般在0-30°之间,90°通常是停机或故障状态。
  • 风速最大值25m/s:这已经接近切出风速了,说明数据覆盖了极端工况。

你看,光是一个describe(),就能发现这么多线索。我在项目中就遇到过,某风场功率曲线异常,一查describe()发现风速数据有大量0值,原来是传感器冻住了。

4.5 数据维度与缺失值概览

最后,我们来看看数据的“身材”和“健康状况”。

# 查看数据维度(行数,列数)
print(f"数据维度:{df.shape}")

# 查看每列缺失值数量
print(f"缺失值统计:\n{df.isnull().sum()}")

输出:

数据维度:(52560, 8)
缺失值统计:
时间戳           0
风速(m/s)       0
有功功率(kW)    0
桨距角(°)       0
发电机转速(rpm)  0
机舱温度(℃)    260
齿轮箱油温(℃)   380
状态码           0
dtype: int64

嗯,果然。机舱温度缺了260条,齿轮箱油温缺了380条。这些缺失值怎么处理?是直接删除,还是填充?这取决于缺失比例和数据的重要性。260/52560 ≈ 0.5%,比例很小,删除影响不大。但如果是关键参数,我建议用前后均值填充。

核心要点:缺失值处理没有标准答案,要根据业务场景来。我个人的原则是:
- 缺失率 < 1%:直接删除该行
- 缺失率 1%-5%:用均值/中位数填充
- 缺失率 > 5%:需要深入分析缺失原因,可能涉及传感器故障

本章知识体系

下面这张图,帮你梳理本章的核心逻辑:

CSV数据读取与初步探索 - 知识体系 1. 读取CSV pd.read_csv() 2. 快速预览 head() 3. 数据概览 info() 4. 统计描述 describe() 5. 维度与缺失值 shape / isnull() 核心目标:快速了解数据全貌 发现异常值 → 识别缺失值 → 判断数据类型 → 评估数据质量

这张图把本章的五个步骤串起来了。从读取CSV开始,到预览、概览、统计描述,最后检查维度与缺失值。每一步都有明确的目的,环环相扣。

好了,这一章的内容就到这里。记住,拿到数据别急着分析,先花5分钟做一遍这个“体检”。你会发现,很多问题在第一步就能暴露出来,省得后面走弯路。


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