NaN与异常值检测

IForest (Isolation Forest) 不支持 NaN,在 fit()predict() 过程中会报 ValueError: Input contains NaN.

解决方案

你有两种主要的方法:

  1. 在异常值检测前处理 NaN(填充 NaN,例如 填充中位数)。
  2. 使用支持 NaN 的方法(例如 IQR, Z-score, LOF)。

方案 1:在检测前处理 NaN

💡 填充 NaN,然后再使用 IForest

from pyod.models.iforest import IForest
import numpy as np
import pandas as pd

class DataAnalyzer:
    def __init__(self, data):
        self.data = data
        self.report = {}

    def generate_report(self):
        self._basic_stats()
        self._missing_analysis()
        self._outlier_detection()
        return self.report

    def _basic_stats(self):
        self.report['stats'] = {
            'num_samples': len(self.data),
            'num_features': len(self.data.columns),
            'dtypes': self.data.dtypes.to_dict()
        }

    def _missing_analysis(self):
        missing = self.data.isnull().mean().to_dict()
        self.report['missing'] = missing

    def _outlier_detection(self):
        numeric_cols = self.data.select_dtypes(include=np.number).columns
        clf = IForest()

        outliers = {}
        for col in numeric_cols:
            col_data = self.data[col].copy()

            # **填充 NaN(例如用中位数)**
            col_data.fillna(col_data.median(), inplace=True)

            clf.fit(col_data.values.reshape(-1, 1))  
            outliers[col] = clf.predict(col_data.values.reshape(-1, 1)).mean()
        
        self.report['outliers'] = outliers

🔥 关键点

  • col_data.fillna(col_data.median(), inplace=True) 处理 NaN,防止 IForest 报错。
  • 适用于数据量较大的情况

方案 2:使用支持 NaN 的方法

方法 1:IQR(四分位距法)

💡 不需要填充 NaN,适用于分布较正常的数据

def _outlier_detection(self):
    numeric_cols = self.data.select_dtypes(include=np.number).columns
    outliers = {}

    for col in numeric_cols:
        Q1 = self.data[col].quantile(0.25)
        Q3 = self.data[col].quantile(0.75)
        IQR = Q3 - Q1

        # 计算异常值(低于 Q1-1.5IQR 或 高于 Q3+1.5IQR)
        is_outlier = (self.data[col] < (Q1 - 1.5 * IQR)) | (self.data[col] > (Q3 + 1.5 * IQR))
        outliers[col] = is_outlier.mean()  # 计算异常值比例

    self.report['outliers'] = outliers

优点

  • 直接支持 NaN,不会报错。
  • 适用于数据呈正态分布的情况。

方法 2:局部异常因子 (LOF)

💡 适用于高维数据

from sklearn.neighbors import LocalOutlierFactor

def _outlier_detection(self):
    numeric_cols = self.data.select_dtypes(include=np.number).columns
    outliers = {}

    for col in numeric_cols:
        col_data = self.data[col].copy()
        col_data.fillna(col_data.median(), inplace=True)  # 先填充 NaN

        lof = LocalOutlierFactor(n_neighbors=20)
        outliers[col] = (lof.fit_predict(col_data.values.reshape(-1, 1)) == -1).mean()

    self.report['outliers'] = outliers

优点

  • 适用于数据分布复杂、高维数据
  • 但计算量较大。

📌 结论

方法适用场景是否支持 NaN计算量适用于高维数据
填充后 IForest适用于大规模数据❌(需填充)✅ 快❌ 不适合
IQR适用于正态分布数据✅ 低
LOF适用于高维数据❌(需填充)❌ 慢

🔥 推荐

  • 如果数据是正常分布,用 IQR(支持 NaN)。
  • 如果数据较复杂,用 LOF
  • 如果你仍想用 IForest,需要填充 NaN

这样你的代码就能既支持 NaN,又能进行异常值检测!🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值