热线电话:13121318867

登录
首页大数据时代Z-score 标准化与异常值处理:从原理到落地的完整方法
Z-score 标准化与异常值处理:从原理到落地的完整方法
2026-11-06
收藏

一、为什么数据要先标准化

拿到一份数据,各列的量纲往往完全不同:年龄单位是"岁"(约 20~60),收入单位是"元"(几千到几万),满意度是 1~5 分,比率是 0~1。如果直接把这几列扔进距离类算法、聚类、PCA、神经网络,数值大的列会天然主导结果——收入波动一个零头,就盖过了满意度全部的差异。

标准化解决的就是这个问题:把不同量纲的变量放到同一把尺子上,让每个变量在分析中拥有对等的话语权。

主流的标准化方法有三类:

方法 公式 输出范围 适用
Z-score 标准化 无固定边界,约 -3~3 近似正态分布的数据
Min-Max 归一化 严格 [0, 1] 有明确边界、需要固定区间
小数定标 随数据浮动 快速粗略处理

其中 Z-score 应用最广,原因后面会讲到:它不仅仅是一个缩放工具,还天然附带了一套异常检测机制。

二、Z-score 的数学含义

2.1 公式

其中 是均值, 是标准差。这个式子做的是两件事:

  1. 中心化:减去均值,把数据中心挪到 0
  2. 缩放:除以标准差,把数据的"宽度"压成 1

变换后,整个数据集均值 = 0,标准差 = 1。

2.2 Z-score 到底在说什么

一个样本的 Z-score,含义是:这个值距离均值有多少个标准差。

  • z = 0:正好在均值上
  • z = 1:比均值高 1 个标准差
  • z = -2:比均值低 2 个标准差
  • z = 3:比均值高 3 个标准差,属于相当罕见的位置

这才是 Z-score 最有价值的解读方式——它把"绝对值"翻译成了"相对位置"。120 分的考试成绩好不好?看它在全班里是均值以上几个标准差,比看绝对分数有意义得多。

2.3 为什么常用 ±3 作为界线

如果数据服从正态分布,经验法则(68-95-99.7 法则)告诉我们:

区间 覆盖比例 落在区间外的概率
68.27% 31.73%
95.45% 4.55%
99.73% 0.27%

也就是说,正态分布下只有 0.27% 的数据会落在 ±3σ 之外。反过来讲,如果一个值 z = 4.5,意味着在正态假设下出现这种情况的概率大约是百万分之三——这基本不可能是正常波动,更可能是异常值。

这就是3σ 法则(拉依达准则)的来源。

三、Z-score 做异常检测的操作流程

3.1 标准四步

import numpy as np
import pandas as pd

# 1. 计算均值与标准差
mu = df['amount'].mean()
sigma = df['amount'].std(ddof=1)

# 2. 计算 Z-score
df['z_amount'] = (df['amount'] - mu) / sigma

# 3. 标记异常
df['is_outlier'] = df['z_amount'].abs() > 3

# 4. 查看异常样本
print(df[df['is_outlier']])

3.2 多变量场景

单变量逐个检测只能发现"某一列极端"的样本。如果异常体现在多个变量的组合偏离(单看每一列都正常,但整体组合很怪),就要用马氏距离(Mahalanobis Distance):

其中 是协方差矩阵。 服从自由度为 p 的卡方分布,可以用 分位数确定阈值。这是 Z-score 在多维空间的推广。

from scipy.spatial.distance import mahalanobis
from scipy.stats import chi2

cov = np.cov(X.T)
inv_cov = np.linalg.inv(cov)
d2 = [mahalanobis(x, mean_vec, inv_cov)**2 for x in X]
threshold = chi2.ppf(0.997, df=X.shape[1])

四、Z-score 的致命短板:它自己会被异常值污染

这是 Z-score 异常检测最容易被忽视的问题。

4.1 问题在哪

Z-score 的均值和标准差,都是用全部数据(包含异常值)算出来的。当数据里存在极端异常值时:

  • 均值被拉偏:一个 1000 万的金额混在正常 1000 元左右的数据里,均值会从 1000 涨到几千
  • 标准差被撑大:标准差被异常值放大几倍,导致正常数据的 z 值都被压缩到 ±1 以内
  • 结果:异常值自己反而"不算异常"

举个具体例子。假设正常数据是 [9, 10, 11, 10, 9, 10, 11],混入一个 100:

data = np.array([9, 10, 11, 10, 9, 10, 11, 100])
z = (data - data.mean()) / data.std(ddof=1)
print(z)  # [ -0.37, -0.30, -0.22, -0.30, -0.37, -0.30, -0.22, 2.36 ]

异常值 100 的 z 只有 2.36,没超过 3,被判为正常。而不含异常值时:

data2 = np.array([9, 10, 11, 10, 9, 10, 11])
z2 = (data2 - data2.mean()) / data2.std(ddof=1)

同样的 100 在这种分布里应该是 z = 30 以上的极端值。异常值把尺子撑变形了,反而藏住了自己。

这就是统计上说的"掩蔽效应"(Masking Effect)。

4.2 更隐蔽的第二重问题:掩盖

多个异常值还可能互相掩护。两个方向相反的大异常值,一个让均值偏高、一个让均值偏低,同时把标准差撑得很大,结果两个都检测不出来。

五、对 Z-score 的稳健替代方案

5.1 修正 Z-score(Robust Z-score / Modified Z-score)

核心思路:把均值和标准差换成不受异常值影响的稳健统计量——中位数和 MAD(Median Absolute Deviation)。

0.6745 这个系数是为了让 MAD 在正态分布下与标准差保持一致的尺度。

from scipy.stats import median_abs_deviation

med = np.median(data)
mad = median_abs_deviation(data, scale='normal')

mz = (data - med) / mad
outliers = data[np.abs(mz) > 3.5]   # 常用阈值 3.5

阈值为什么是 3.5 而不是 3:Iglewicz 和 Hoaglin 的建议值,因为 MAD 的分布比标准差更"瘦",需要略微放宽。

MAD 的崩溃点是 50%,也就是接近一半的数据是异常值时,它依然稳定;而标准差的崩溃点是 0%——一个异常值就能毁掉它。

5.2 IQR 法(箱线图法则)

完全不依赖均值和标准差,只用四分位数:

其中 。这是箱线图"须线"的判定逻辑,比 3σ 更不受极端值干扰。

q1, q3 = np.percentile(data, [25, 75])
iqr = q3 - q1
lower, upper = q1 - 1.5*iqr, q3 + 1.5*iqr

补充:箱线图须线的系数在不同软件里不一样。Tukey 原始定义用 1.5×IQR,而 Excel 的箱线图实际画到的是 1.5×IQR 之外的最小/最大观测值,SPSS 也有自己的实现差异,比对时要注意。

”

5.3 分位数截断(Winsorize / 缩尾)

不删除异常值,而是把它们"压"到边界值:

from scipy.stats.mstats import winsorize
data_w = winsorize(data, limits=[0.05, 0.05])   # 两端各截 5%

适用:样本量小、删不起数据;或者异常值是真实存在只是极端的情况(如头部用户的巨额消费)。

5.4 对数变换

对于右偏严重的金额、流量类数据(少数大值拉长尾巴),取对数能先让分布接近正态,再用 Z-score 就合理得多:

data_log = np.log1p(data)   # log(1+x),避免 0 值

5.5 分箱离散化

把连续值切成分箱,从根上消除异常值的影响。适合用于建模特征而非原始分析。

六、检测出异常值之后怎么处理

检测只是第一步,处理方式取决于异常值的性质:

处理方式 做法 适用场景 风险
直接删除 剔除异常样本 明显是录入错误、测量失误 样本量减少;可能删掉真实业务信号
缩尾处理 压到边界值 异常值真实存在但极端 改变分布形态
视为缺失 置为 NaN 后填充 不确定异常来源 填充可能引入新偏差
保留并标记 加标志位单独建模 异常本身有业务价值(欺诈、故障) 模型需支持标志特征
分组建模 正常/异常分开建 两类样本机制不同 增加建模复杂度

关键判断问题:这个"异常"是错误,还是真实?

  • 录入错误、单位错位、传感器故障 → 删除或修正
  • 真实极端业务现象(大客户、异常订单、欺诈)→ 保留、标记,往往才是最有价值的样本

现实中大量分析师犯的错是:一律按"异常即脏数据"处理,把最有业务价值的样本清掉了。

七、Z-score 标准化的适用条件与误用

7.1 什么时候能用

  1. 数据近似正态分布:这是 3σ 法则成立的前提
  2. 样本量足够大:均值和标准差才稳定
  3. 异常值占比很低:否则掩蔽效应会让检测失效

7.2 什么时候不能用

  • 严重偏态分布(如收入、订单金额):先做对数变换
  • 分布是双峰或多峰:Z-score 会把两个峰之间的正常值判成异常
  • 本身就是分类/有序变量:Z-score 没有意义
  • 小样本(n < 30):标准差估计不稳定

7.3 训练集与测试集的标准化(工程要点)

做机器学习时,一个必须遵守的规则:用训练集的均值和标准差,去标准化测试集和新数据,不能用全量数据算参数。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)   # 在训练集上 fit
X_test_scaled = scaler.transform(X_test)         # 用训练集参数 transform

如果对全体数据先算均值方差再切分,测试集的信息就泄露到训练过程里了,这叫数据泄露(Data Leakage),会让模型评估虚高。

八、完整落地示例

一个完整的流程应该是这样的:

import numpy as np
import pandas as pd
from scipy.stats import median_abs_deviation

def detect_outliers(series, method='robust', threshold=3.5):
    """多方法异常检测"""
    s = series.dropna()

    if method == 'zscore':
        mu, sigma = s.mean(), s.std(ddof=1)
        z = (s - mu) / sigma
        return s[np.abs(z) > 3]

    elif method == 'robust':
        med = s.median()
        mad = median_abs_deviation(s, scale='normal')
        mz = (s - med) / mad
        return s[np.abs(mz) > threshold]

    elif method == 'iqr':
        q1, q3 = s.quantile([0.25, 0.75])
        iqr = q3 - q1
        lo, hi = q1 - 1.5*iqr, q3 + 1.5*iqr
        return s[(s < lo) | (s > hi)]

# 使用
out_z = detect_outliers(df['amount'], 'zscore')
out_r = detect_outliers(df['amount'], 'robust')
out_i = detect_outliers(df['amount'], 'iqr')

print(f"Z-score 检出:{len(out_z)} 个")
print(f"稳健Z 检出:{len(out_r)} 个")
print(f"IQR 检出:{len(out_i)} 个")

实践中建议三种方法交叉验证:三种都判为异常的点,基本可以确认是真异常;只有一种判异常的,需要人工复核业务含义。

九、总结

Z-score 标准化和异常检测,本质是同一个公式的两种用途:

  • 标准化:把不同量纲的变量放到同一尺度,为建模和比较做准备
  • 异常检测:用 ±3σ 的边界识别落在分布尾部的极端值

但必须清楚它的局限:Z-score 依赖均值和标准差,这两个统计量本身对异常值极度敏感。当数据被污染时,异常值会把尺子撑变形,把自己藏起来——这就是掩蔽效应。

工程上更稳妥的做法是:

  1. 先看分布形态,偏态数据先做变换
  2. 优先用稳健方法(MAD、IQR、Winsorize)做检测
  3. 检出后先判断"是错误还是真实",再决定删除还是保留
  4. 建模时严格区分 fit 与 transform 的数据范围,避免信息泄露

方法本身不难,难的是知道什么时候不该用它。

推荐学习书籍 《CDA一级教材》适合CDA一级考生备考,也适合业务及数据分析岗位的从业者提升自我。完整电子版已上线CDA网校,累计已有10万+在读~ !

免费加入阅读:https://edu.cda.cn/goods/show/3151?targetId=5147&preview=0

数据分析师资讯
更多

OK
客服在线
立即咨询
客服在线
立即咨询