异常值检验的一些方法
Posted Icy Hunter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异常值检验的一些方法相关的知识,希望对你有一定的参考价值。
异常值检验的一些方法
1.局部离群因子检测(LOF)
LOF算法对数据分布假设没什么要求,能够量化每个数据点的异常程度,是一种基于密度的检测异常值的方法。LOF算法认为非离群点对象周围的密度与其邻域周围的密度类似,而离群点对象周围的密度显著不同于其邻域周围的密度。其核心思想就是看局部的密度与周围的密度相比较,如果局部密度相对稀疏,则可认为是离群值,即异常值。
具体可以参考一文读懂异常检测 LOF 算法(Python代码)讲的还是比较清楚的。
调用sklearn可以较快的实现:
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
from sklearn.decomposition import PCA
# 导入鸢尾花的数据集
iris = datasets.load_iris()
# PCA降维至2维
X = PCA(n_components=2).fit_transform(iris.data)
# 定义一个LOF模型,contamination能够自己定义异常比例,默认自动选取
model = LocalOutlierFactor(n_neighbors=10)
# 训练模型
model.fit(X)
# 预测模型
# 这里是训练数据中就包含着异常值的话,那么适用训练时novelty默认为False,给训练数据打标签使用fit_predict(x)
y = model.fit_predict(X) # 若样本点正常,返回1,不正常,返回-1
# 可视化预测结果
plt.scatter(X[:, 0], X[:, 1], c=y) # 样本点的颜色由y值决定
plt.show()
黑色的点即为检测出的异常值。
2.MADe法
from sklearn import datasets
import pandas as pd
import numpy as np
iris = datasets.load_iris()
X = iris.data[:, 0] # 换成需要检测的一维数据即可
X = pd.DataFrame(X)
col = 0 # 需要检验的dataframe的列
M = X[col].median()
MAD = (np.abs(X[col] - X[col].median())).median()
down = M - 3 * MAD * 1.483
up = M + 3 * MAD * 1.483
error = X[(X[col] < down) | (X[col] > up)]
print(down)
print(up)
if len(error) == 0:
print("此方法未检测出异常值")
else:
print(error)
运行结果
3.修正的Z得分法
from sklearn import datasets
import pandas as pd
import numpy as np
iris = datasets.load_iris()
X = iris.data[:, 0] # 换成需要检测的一维数据即可
X = pd.DataFrame(X)
col = 0
MAD = (np.abs(X[col] - X[col].median())).median()
M = np.abs(0.6745 * (X[col] - X[col].median()) / MAD)
if len(M[M > 3.5]) == 0:
print("检测无异常值")
else:
print(M[M > 3.5])
说明此方法在此数据中没有检测出异常值
4.boxplot法
import numpy as np
from statsmodels.stats.stattools import medcouple
import pandas as pd
np.random.seed(0)
data = np.random.rand(10000)
data[0] = data[0] * 3
data = pd.DataFrame(data)
col = 0 # 所选需要检验的dataframe的列
des = data[col].describe()
Q1 = des.loc["25%"]
Q3 = des.loc["75%"]
IQR = Q3 - Q1
I_L = Q1 - 1.5 * IQR
I_U = Q3 + 1.5 * IQR
O_L = Q1 - 3 * IQR
O_U = Q3 + 3 * IQR
error = data[(data[col] < O_L) | (data[col] > O_U)]
error_may = data[((data[col] > O_L) & (data[col] < I_L)) | ((data[col] < O_U) & (data[col] > I_U))]
if len(error) == 0 and len(error_may) == 0:
print("未检测出异常值")
if len(error_may) != 0:
print("可能为异常值:")
print(error_may)
if len(error) != 0:
print("检测出异常值为")
print(error)
结果
5.修正的boxplot法
import numpy as np
from statsmodels.stats.stattools import medcouple
import pandas as pd
np.random.seed(0)
data = np.random.rand(10000)
data[0] = data[0] * 3
data = pd.DataFrame(data)
col = 0
if len(data[col]) > 10000: # 大于10000就抽样计算估计数据的MC
samples = data[col].sample(n=10000)
else:
samples = data[col]
MC = medcouple(samples)
des = data[col].describe()
Q1 = des.loc["25%"]
Q3 = des.loc["75%"]
IQR = Q3 - Q1
L = 0
U = 0
if MC >= 0:
L = Q1 - 1.5 * np.exp(-3.5 * MC) * IQR
U = Q3 + 1.5 * np.exp(4 * MC) * IQR
else:
L = Q1 - 1.5 * np.exp(-4 * MC) * IQR
U = Q3 + 1.5 * np.exp(3.5 * MC) * IQR
print(L)
print(U)
error = data[(data[col] < L) | (data[col] > U)]
if len(error) == 0:
print("未检测出异常值")
else:
print("检测出的异常值为")
print(error)
结果
以上是关于异常值检验的一些方法的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用car包的outlierTest函数通过假设检验的方法检测回归模型中的异常值(outlier)输出异常值对应的统计量p值以及Bonferonnii校正p值