【算法】基于中位数和MAD鲁棒平均值计算算法

问题

在项目中,需要对异常值进行剔除,需要一种鲁棒性比较好的方法,总结了一个实践方法。

方法

基于中位数和MAD(中位数绝对偏差)的鲁棒平均值计算算法的详细过程,按照您要求的步骤分解:


算法过程

过程:
    1. 先使用中位数作为初始估计
    1. 计算MAD作为离散度度量
    1. 排除偏离中位数超过3倍MAD的数据点
    1. 对剩余数据计算平均值
输入
  • 数据集 data = [x₁, x₂, ..., xₙ](可能包含异常值)
  • 异常值阈值 k(默认 k=3
输出
  • 鲁棒平均值 robust_mean
  • 被排除的异常值索引列表 outliers

步骤 1:计算中位数(初始估计)

中位数对异常值不敏感,是数据中心的鲁棒估计。

python 复制代码
median = np.median(data)  # 中位数

例子
data = [10, 12, 11, 15, 10, 9, 11, 10, 100, 8, 9, 10, 12, -50]

排序后:[-50, 8, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 15, 100]

中位数 median = 10(第7和第8个值的平均)


步骤 2:计算MAD(离散度度量)

MAD(Median Absolute Deviation)是数据与中位数绝对偏差的中位数,对异常值鲁棒。

python 复制代码
deviations = np.abs(data - median)  # 各点与中位数的绝对偏差
mad = np.median(deviations)         # MAD
mad = mad * 1.4826                  # 调整因子(使MAD≈标准差)

调整因子解释

  • 对于正态分布,标准差 σ ≈ 1.4826 × MAD
  • 调整后,k=3 对应正态分布的3σ准则(覆盖99.7%数据)。

例子

绝对偏差 deviations = [60, 2, 1, 5, 0, 1, 1, 0, 90, 2, 1, 0, 2, 40]

排序后:[0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 5, 40, 60, 90]

MAD = 1(中位数)

调整后 mad = 1.4826


步骤 3:排除异常值(3×MAD准则)

标记所有满足 |xᵢ - median| > k × mad 的点为异常值。

python 复制代码
outlier_mask = deviations > (k * mad)  # 异常值掩码
clean_data = data[~outlier_mask]       # 清洗后的数据

例子k=3):

阈值 3 × 1.4826 ≈ 4.45

异常值条件:|xᵢ - 10| > 4.45

  • 100|100 - 10| = 90 > 4.45 → 异常
  • -50|-50 - 10| = 60 > 4.45 → 异常
    其他点均保留。

步骤 4:计算剩余数据的平均值

对清洗后的数据求算术平均。

python 复制代码
robust_mean = np.mean(clean_data)

例子

清洗后数据:[10, 12, 11, 15, 10, 9, 11, 10, 8, 9, 10, 12]

鲁棒平均值 robust_mean = 10.5


完整代码实现

python 复制代码
import numpy as np

def robust_mean(data, k=3):
    data = np.asarray(data)
    median = np.median(data)
    
    # 计算MAD并调整
    deviations = np.abs(data - median)
    mad = np.median(deviations) * 1.4826
    
    # 处理MAD为0的情况(所有数据相同)
    if mad == 0:
        return median, np.array([])
    
    # 标记并排除异常值
    outlier_mask = deviations > (k * mad)
    clean_data = data[~outlier_mask]
    
    return np.mean(clean_data), np.where(outlier_mask)[0]

# 示例
data = [10, 12, 11, 15, 10, 9, 11, 10, 100, 8, 9, 10, 12, -50]
mean, outliers = robust_mean(data)
print(f"鲁棒平均值: {mean}, 异常值索引: {outliers}")

算法优点

  1. 鲁棒性:中位数和MAD均不受极端值影响。
  2. 自动阈值k=3 对应正态分布的3σ准则,可调整(如严格检测用 k=2.5)。
  3. 适用性:适合传感器数据(如鸡秤)、金融数据等含离群点的场景。

可视化

复制代码
数据分布: [-50, 8, 9, 9, 10, 10, 10, 10, 11, 11, 12, 12, 15, 100]
          ↑______中位数=10______↑           ↑
          异常值(-50)                    异常值(100)
相关推荐
老迟到的茉莉7 分钟前
Hermes 是谁?跟 Claude Code 差在哪
开发语言·python
学逆向的12 分钟前
汇编——内存
开发语言·汇编·算法·网络安全
tachibana217 分钟前
hot100 翻转二叉树(226)
java·数据结构·算法·leetcode
Day(AKA Elin)31 分钟前
【Day】MTP(Multi Token Prediction)技术学习
python·深度学习·学习·llama
生戎马1 小时前
高光谱拼接算法(七)USAC
算法
PhotonixBay2 小时前
共聚焦成像核心原理:针孔、PSF与三维形貌测量技术
人工智能·测试工具·算法
程序员小远2 小时前
接口测试之文件上传
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
江华森2 小时前
Python 实现高德地图找房(三):地图可视化与高德 JS API
开发语言·javascript·python
来一碗刘肉面2 小时前
C++中的引用语法
c++·算法
曲幽2 小时前
Anki插件开发必知必会:钩子函数与右键菜单定制
python·fastapi·anki·menu·browser·addons