4. 失效数据基础
数据采集回来,十有八九是脏的。这是我干失效分析这些年最深的体会。
传感器掉线、通信丢包、人为误操作……原始数据里什么妖魔鬼怪都有。你直接拿这些数据去建模,结果就是 garbage in, garbage out。所以,数据清洗不是锦上添花,是必修课。
这一章,我把几个最常用的预处理手段掰开揉碎讲清楚。都是我在产线上踩过坑、填过土之后沉淀下来的东西。
4.1 缺失值处理
缺失值是最常见的问题。说白了,就是某个时间点或某个字段,数据没了。
4.1.1 缺失机制分类
| 类型 | 含义 | 举例 |
|---|---|---|
| MCAR | 完全随机缺失 | 传感器偶尔被鸟撞了一下,随机丢包 |
| MAR | 随机缺失(依赖其他变量) | 高温工况下,某个温度探头容易失效 |
| MNAR | 非随机缺失(依赖自身) | 压力过高时,压力传感器直接烧毁 |
我个人习惯,拿到数据先做缺失值可视化。用热图或者条形图看一眼缺失分布,心里就有数了。
4.1.2 常用处理方法
- 直接删除: 缺失比例小(<5%),且是MCAR。简单粗暴,但样本少时慎用。
- 均值/中位数填充: 数值型变量,分布对称用均值,有偏态用中位数。我在项目里遇到过,填充均值后模型反而变差了——因为破坏了原始分布。
- 前向/后向填充: 时间序列数据常用。比如传感器在10:00:01有值,10:00:02缺失,用前一个值顶上去。适合缓慢变化的物理量。
- 插值法: 线性插值、样条插值。适合连续变化的数据,比如温度、压力曲线。
- 模型预测填充: 用其他字段做回归或KNN预测缺失值。精度高,但计算量大。
4.2 异常值检测
异常值,就是那些明显偏离正常范围的点。在失效分析里,异常值往往就是故障的前兆。所以,别急着删,先看看它是不是宝贝。
4.2.1 3σ 法则(拉依达准则)
假设数据服从正态分布。均值 ± 3倍标准差以外的点,视为异常。
import numpy as np
def detect_outliers_3sigma(data):
mean = np.mean(data)
std = np.std(data)
lower = mean - 3 * std
upper = mean + 3 * std
outliers = (data < lower) | (data > upper)
return outliers
这个方法的缺点很明显——它对正态性要求高。如果数据本身有偏态,或者有多个峰值,3σ 会漏检或误检。我记得有一次分析振动数据,3σ 把正常的高频波动全标成了异常,差点把工程师带沟里去。
4.2.2 IQR 方法(四分位距法)
不依赖正态分布,鲁棒性更好。用 Q1 和 Q3 算 IQR,然后划定上下界。
def detect_outliers_iqr(data):
Q1 = np.percentile(data, 25)
Q3 = np.percentile(data, 75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = (data < lower) | (data > upper)
return outliers
4.2.3 两种方法对比
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 3σ | 正态分布、对称数据 | 理论成熟、计算快 | 对偏态敏感、受极端值影响大 |
| IQR | 偏态分布、含噪声数据 | 鲁棒性强、不依赖分布 | 对尾部数据不敏感 |
我个人习惯,先用 IQR 做初筛,再用 3σ 做复核。两套方法都标记为异常的,基本可以确定是真正的异常点。
4.3 数据标准化与归一化
不同特征的量纲不一样。比如温度是 0~100℃,压力是 0~10 MPa。如果不做标准化,模型会天然偏向数值大的特征。说白了,就是尺子不一样,没法比。
4.3.1 归一化(Min-Max Scaling)
把数据缩放到 [0, 1] 区间。
def min_max_scaling(data):
min_val = np.min(data)
max_val = np.max(data)
scaled = (data - min_val) / (max_val - min_val)
return scaled
适合数据有明确上下界的场景,比如图像像素值。但缺点也很明显——对异常值敏感。如果有一个极端大值,其他数据会被压缩到很小。
4.3.2 标准化(Z-score Normalization)
把数据变成均值为0、标准差为1的分布。
def z_score_normalization(data):
mean = np.mean(data)
std = np.std(data)
normalized = (data - mean) / std
return normalized
适合数据近似正态分布的场景。很多机器学习算法(如SVM、PCA)默认数据是标准化的。我在做振动信号分析时,几乎都用 Z-score,因为它保留了原始数据的分布形状。
4.3.3 怎么选?
| 场景 | 推荐方法 | 原因 |
|---|---|---|
| 数据有界、无异常值 | 归一化 | 保持原始比例 |
| 数据有异常值、分布未知 | 标准化 | 鲁棒性更好 |
| 需要保留稀疏性 | 标准化 | 归一化会破坏稀疏结构 |
| 神经网络输入 | 归一化 | 加速收敛 |
4.4 时间序列对齐
多源数据采集,时间戳往往不一致。有的传感器采样频率是 100Hz,有的是 10Hz,还有的是事件触发。不对齐,就没法做联合分析。
4.4.1 重采样
把不同频率的数据统一到同一个时间基准上。常用方法:
- 降采样: 高频数据变低频。用均值、最大值或最小值聚合。比如把 100Hz 的振动数据降成 1Hz,取每秒的 RMS 值。
- 升采样: 低频数据变高频。用插值或填充。比如把 1Hz 的温度数据升到 10Hz,用线性插值填补中间点。
import pandas as pd
# 假设有两个时间序列
ts1 = pd.Series([1, 2, 3], index=pd.to_datetime(['2024-01-01 10:00:00',
'2024-01-01 10:00:01',
'2024-01-01 10:00:02']))
ts2 = pd.Series([10, 20], index=pd.to_datetime(['2024-01-01 10:00:00',
'2024-01-01 10:00:02']))
# 统一重采样到 1Hz,用前向填充
ts1_resampled = ts1.resample('1S').ffill()
ts2_resampled = ts2.resample('1S').ffill()
4.4.2 时间窗口对齐
不是所有场景都需要精确到毫秒。有时候,用滑动窗口做对齐更实用。比如,把 10 秒内的所有数据点归到一个窗口里,取统计特征(均值、方差、峰值)。
4.4.3 对齐中的常见坑
- 时区问题: 不同设备可能用不同时区。统一转成 UTC。
- 时钟漂移: 设备长时间运行后,本地时钟会偏差。需要 NTP 同步或事后校正。
- 丢包导致的时间戳空洞: 重采样后会出现 NaN。我一般用前向填充+插值组合,实在不行就标记为缺失。
4.5 本章知识体系
下面这张图,把数据清洗与预处理的几个核心模块串起来了。你可以把它当成一个检查清单,每次做数据预处理时对照着走一遍。
数据清洗这件事,没有银弹。每个项目的数据都不一样,但方法论是通用的。你只要把缺失、异常、量纲、时间这四个维度理清楚,预处理这关就算过了。