IForest
(Isolation Forest) 不支持 NaN
,在 fit()
或 predict()
过程中会报 ValueError: Input contains NaN.
。
✅ 解决方案
你有两种主要的方法:
- 在异常值检测前处理
NaN
(填充NaN
,例如填充中位数
)。 - 使用支持
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
,又能进行异常值检测!🚀