scipy.stats可以识别并掩盖明显的异常值吗?

时间:2012-04-19 15:14:37

标签: python statistics scipy linear-regression

使用scipy.stats.linregress,我对一些高度相关的x,y实验数据进行简单的线性回归,最初目测检查每个x,y散点图的异常值。更一般地(即以编程方式)是否有一种识别和屏蔽异常值的方法?

4 个答案:

答案 0 :(得分:24)

statsmodels包具有您所需的功能。看看这个小代码片段及其输出:

# Imports #
import statsmodels.api as smapi
import statsmodels.graphics as smgraphics
# Make data #
x = range(30)
y = [y*10 for y in x]
# Add outlier #
x.insert(6,15)
y.insert(6,220)
# Make graph #
regression = smapi.OLS(x, y).fit()
figure = smgraphics.regressionplots.plot_fit(regression, 0)
# Find outliers #
test = regression.outlier_test()
outliers = ((x[i],y[i]) for i,t in enumerate(test) if t[2] < 0.5)
print 'Outliers: ', list(outliers)

Example figure 1

Outliers: [(15, 220)]

修改

使用较新版本的statsmodels,情况有所改变。这是一个新的代码段,显示了相同类型的异常值检测。

# Imports #
from random import random
import statsmodels.api as smapi
from statsmodels.formula.api import ols
import statsmodels.graphics as smgraphics
# Make data #
x = range(30)
y = [y*(10+random())+200 for y in x]
# Add outlier #
x.insert(6,15)
y.insert(6,220)
# Make fit #
regression = ols("data ~ x", data=dict(data=y, x=x)).fit()
# Find outliers #
test = regression.outlier_test()
outliers = ((x[i],y[i]) for i,t in enumerate(test.icol(2)) if t < 0.5)
print 'Outliers: ', list(outliers)
# Figure #
figure = smgraphics.regressionplots.plot_fit(regression, 1)
# Add line #
smgraphics.regressionplots.abline_plot(model_results=regression, ax=figure.axes[0])

Example figure 2

Outliers: [(15, 220)]

答案 1 :(得分:7)

scipy.stats没有直接用于异常值的东西,所以回答一些链接和statsmodels的广告(这是scipy.stats的统计补充)

用于识别异常值

http://jpktd.blogspot.ca/2012/01/influence-and-outlier-measures-in.html

http://jpktd.blogspot.ca/2012/01/anscombe-and-diagnostic-statistics.html

http://statsmodels.sourceforge.net/devel/generated/statsmodels.stats.outliers_influence.OLSInfluence.html

而不是屏蔽,更好的方法是使用强大的估算器

http://statsmodels.sourceforge.net/devel/rlm.html

带有示例,遗憾的是当前没有显示图表 http://statsmodels.sourceforge.net/devel/examples/generated/tut_ols_rlm.html

RLM下调异常值。估计结果具有weights属性,对于异常值,权重小于1.这也可用于查找异常值。如果有几个异常值,RLM也会更强大。

答案 2 :(得分:6)

  

更一般地(即以编程方式)是否有一种识别和屏蔽异常值的方法?

存在各种离群检测算法; scikit-learn实现了其中的一些。

[免责声明:我是一名scikit-learn贡献者。]

答案 3 :(得分:0)

也可以使用scipy.optimize.least_squares限制异常值的影响。特别是,请查看f_scale参数:

  

内部和外部残差之间的软边际值,默认值为1.0。 ...此参数对loss ='linear'没有影响,但对于其他损失值,它至关重要。

在页面上,他们比较了3种不同的功能:普通least_squares和两种涉及f_scale的方法:

res_lsq =     least_squares(fun, x0, args=(t_train, y_train))
res_soft_l1 = least_squares(fun, x0, loss='soft_l1', f_scale=0.1, args=(t_train, y_train))
res_log =     least_squares(fun, x0, loss='cauchy', f_scale=0.1, args=(t_train, y_train))

Least squares comparison

可以看出,正态最小二乘受数据异常值的影响更大,并且值得使用不同的loss函数和不同的f_scales。可能的损失函数(取自文档):

‘linear’ : Gives a standard least-squares problem.
‘soft_l1’: The smooth approximation of l1 (absolute value) loss. Usually a good choice for robust least squares.
‘huber’  : Works similarly to ‘soft_l1’.
‘cauchy’ : Severely weakens outliers influence, but may cause difficulties in optimization process.
‘arctan’ : Limits a maximum loss on a single residual, has properties similar to ‘cauchy’.

有关强大非线性回归的scipy cookbook has a neat tutorial