4. 数据加载与初步探索:用Pandas看清你的数据

各位工程师朋友,欢迎来到实战环节。

前面我们聊了风机故障诊断的整体思路,也搭建好了分析环境。但说实话,真正动手的第一步,往往是最容易出问题的。我见过不少项目,模型跑得飞起,结果回头一看——数据加载阶段就埋了雷。

今天我们就来聊聊,怎么用Pandas把数据请进来,并且快速摸清它的底细。

4.1 数据加载:把文件变成DataFrame

我个人习惯,拿到数据的第一件事,不是急着分析,而是先看一眼文件长什么样。风机数据通常以CSV格式存储,比如这样:

import pandas as pd

# 加载风机振动数据
df = pd.read_csv('fan_vibration_data.csv')
print('数据加载完成,共 {} 行 {} 列'.format(df.shape[0], df.shape[1]))

嗯,这里要注意。read_csv()有很多参数,我建议你养成两个好习惯:

  • 指定编码:中文数据经常遇到编码问题,加个encoding='utf-8''gbk'
  • 检查分隔符:有些文件用制表符或分号,记得设置sep='\t'sep=';'
我的小经验:有一次客户发来的数据,文件名是CSV,打开一看全是乱码。后来发现是Excel另存时用了GB2312编码。从那以后,我加载数据前都会先看一眼文件头。

4.2 快速浏览:head()和tail()

数据加载进来了,别急着往下走。先看看数据长什么样。

# 查看前5行
print(df.head())

# 查看后5行
print(df.tail())

head()默认显示前5行,你可以传参,比如head(10)。我一般先看5行,如果感觉数据怪怪的,再看10行。

你想想看,如果数据加载错了,或者列名对不上,这一步就能发现。我曾经遇到过,客户说数据有100个传感器通道,结果head()一看,只有99列——少了一列数据,后面所有分析都得重来。

4.3 数据概览:info()告诉你一切

info()是我最常用的函数之一。它就像数据的体检报告,一行一行告诉你:

df.info()

输出大概长这样:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 12 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   timestamp       10000 non-null  object 
 1   vibration_x     10000 non-null  float64
 2   vibration_y     9998 non-null   float64
 3   vibration_z     10000 non-null  float64
 4   temperature     10000 non-null  float64
 5   rpm             10000 non-null  int64  
 6   current         9995 non-null   float64
 7   voltage         10000 non-null  float64
 8   power           10000 non-null  float64
 9   wind_speed      10000 non-null  float64
 10  fault_label     10000 non-null  int64  
 11  sensor_id       10000 non-null  object 
dtypes: float64(8), int64(2), object(2)
memory usage: 937.5 KB

这里信息量很大,我带你拆解一下:

  • 行数:10000条记录,样本量还不错
  • 列数:12列,包含时间戳、振动、温度、电流等
  • 非空计数:注意看,vibration_y只有9998个非空,current只有9995个——有缺失值!
  • 数据类型:float64是数值型,int64是整数型,object一般是字符串或时间戳
注意:如果某列显示为object,但你知道它应该是数值,那就要小心了。我遇到过,传感器ID被读成了数字,但其实是字符串。这种类型错误,后面做计算时会直接报错。

4.4 统计描述:describe()的妙用

info()告诉你数据有没有缺失,describe()则告诉你数据长什么样——均值、标准差、最小值、最大值等等。

df.describe()

输出示例:

vibration_x vibration_y vibration_z temperature rpm current
count 10000.0 9998.0 10000.0 10000.0 10000.0 9995.0
mean 2.34 1.89 3.12 45.6 1500.0 12.5
std 0.87 0.92 1.23 5.2 120.0 3.1
min 0.12 0.08 0.15 28.0 800.0 2.1
25% 1.56 1.23 2.01 41.0 1400.0 10.2
50% 2.30 1.85 3.08 45.0 1500.0 12.3
75% 3.10 2.50 4.15 50.0 1600.0 14.8
max 8.90 7.60 9.80 68.0 1800.0 25.0

看这个表,你能发现什么?

  • 振动值:vibration_x的均值2.34,最大值8.9——这个最大值明显偏高,可能是故障状态
  • 温度:最高68度,正常风机运行温度一般在40-55度,68度有点高了
  • 转速:800-1800 RPM,范围合理,但800转是不是停机状态?

说白了,describe()就是帮你快速建立对数据的直觉。我每次拿到新数据,都会先跑一遍describe(),然后心里就有数了。

4.5 缺失值检查:别让NaN坑了你

刚才info()里我们看到有缺失值。现在来精确检查一下:

# 检查每列缺失值数量
print(df.isnull().sum())

# 缺失值占比
print(df.isnull().sum() / len(df) * 100)

输出:

timestamp         0
vibration_x       0
vibration_y       2
vibration_z       0
temperature       0
rpm               0
current           5
voltage           0
power             0
wind_speed        0
fault_label       0
sensor_id         0
dtype: int64

vibration_y缺失2条,current缺失5条。占比很小,不到0.1%。

我的处理原则:缺失值占比小于1%,直接删除这些行。占比在1%-5%,考虑用均值或中位数填充。超过5%,就要认真分析缺失原因了——是不是传感器坏了?还是数据采集有问题?

我曾经遇到过一个项目,电流数据缺失了30%。一开始以为是采集故障,后来发现是某个传感器在特定工况下会掉线。如果不分析原因直接填充,模型就会学到错误规律。

4.6 数据类型检查:别让类型坑了你

数据类型不对,后面所有计算都会出问题。我建议你养成这个习惯:

# 查看每列数据类型
print(df.dtypes)

# 单独检查某列
print(df['timestamp'].dtype)

常见问题:

  • 时间戳是object:需要转换成datetime类型,方便后续按时间分析
  • 数值列是object:可能混入了字符串,比如'12.5a'这种脏数据
  • 整数列是float:可能因为有缺失值,Pandas自动转成了float

转换方法:

# 时间戳转换
df['timestamp'] = pd.to_datetime(df['timestamp'])

# 数值列转换(遇到错误就变成NaN)
df['current'] = pd.to_numeric(df['current'], errors='coerce')

4.7 本章知识体系

下面这张图,帮你理清数据加载与初步探索的完整流程:

数据加载与初步探索流程 1. 数据加载 pd.read_csv() 2. 快速浏览 head() / tail() 3. 数据概览 info() 4. 统计描述 describe() 检查要点 ✅ 行数列数是否正确 ✅ 列名是否与预期一致 ✅ 数据类型是否合理 ✅ 缺失值数量及占比 ✅ 数值范围是否异常 ✅ 时间戳格式是否正确 ✅ 是否有重复行 ✅ 分类列取值是否合理 常见问题 ⚠️ 编码错误导致乱码 ⚠️ 分隔符不匹配 ⚠️ 数值列混入字符串 ⚠️ 缺失值被忽略

4.8 实战小贴士

最后,分享几个我常用的检查套路:

# 一键检查套路
def quick_check(df):
    print("="*50)
    print("数据形状:", df.shape)
    print("="*50)
    print("列名:\n", df.columns.tolist())
    print("="*50)
    print("数据类型:\n", df.dtypes)
    print("="*50)
    print("缺失值:\n", df.isnull().sum())
    print("="*50)
    print("统计描述:\n", df.describe())
    print("="*50)
    print("重复行数:", df.duplicated().sum())
    
quick_check(df)

这个函数我用了好几年,每次拿到新数据,先跑一遍,心里就有底了。

我的习惯:把quick_check()保存在一个工具脚本里,每次新项目直接导入。省时省力,还能保证不遗漏检查项。

好了,数据加载和初步探索就聊到这里。记住一句话:数据质量决定了分析质量。这一步花的时间,后面都会加倍还给你。


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