ADJUSTED BOXPLOT: 偏态分布的异常检测

Boxplot是一个常用的了解数据分布的工具,在数据预处理阶段也常用boxplot剔除离群点,但是当数据是一个偏态分布的时候,boxplot将许多点误分类为离群点。《AN ADJUSTED BOXPLOT FOR SKEWED
DISTRIBUTIONS》是一篇经典的修正boxplot在偏态分布数据上的误报问题的文章。

1. 传统boxplot方法

对于一组数据 X n = { x 1 , x 2 , x 3 , . . . , x n } X_n=\{x_1,x_2,x_3,...,x_n\} Xn={x1,x2,x3,...,xn},计算Q1(第一四分位数), Q3(第三四分位数), IQR(四分位距),然后得到Tukey bound:
[ Q 1 − 1.5 ∗ I Q R , Q 3 + 1.5 ∗ I Q R ] [Q_1-1.5*IQR, Q_3+1.5*IQR] [Q11.5IQR,Q3+1.5IQR]
boxplot 方法认为落在tukey bound外的数据为离群值。

缺点:该上下界是基于数据时对称分布得到的,当数据是偏态分布时tukey bound表现得并不好。

2. 通用的boxplot方法

medcouple

medcouple(MC)是一个健壮的,用于描述连续单变量分布(F)偏度的统计量:
M C ( F ) = m e d i a n x i < m F < x j h ( x i , x j ) MC(F)=\mathop{median}\limits_{x_i<m_F<x_j} h(x_i,x_j) MC(F)=xi<mF<xjmedianh(xi,xj)

m F m_F mF是F的中值, x i , x j x_i,x_j xi,xj是F中的样本,核函数h(x)定义如下:
h ( x i , x j ) = ( x j − m F ) − ( m F − x i ) x j − x i h(x_i,x_j)=\frac{(x_j-m_F)-(m_F-x_i)}{x_j-x_i} h(xi,xj)=xjxi(xjmF)(mFxi)
MC取值在[-1,1],MC>0分布右偏,MC<0分布左偏。对于对称分布,MC=0。

boxplot修正

接下来利用MC对tukey bound进行偏态修正,这里引入修正函数 h l ( M C ) h_l(MC) hl(MC) h r ( M C ) h_r(MC) hr(MC)
[ Q 1 − h l ( M C ) ∗ I Q R , Q 3 + h r ( M C ) ∗ I Q R ] [Q_1-h_l(MC)*IQR, Q_3+h_r(MC)*IQR] [Q1hl(MC)IQR,Q3+hr(MC)IQR]
这里需要满足 h l ( 0 ) = h r ( 0 ) = 1.5 h_l(0)=h_r(0)=1.5 hl(0)=hr(0)=1.5,以保证和原始boxplot在对称分布数据中取得同样的效果。

然后作者研究了3种简单的,不需要太多参数的关于修正函数的模型:

  1. 线性模型: h l ( M C ) = 1.5 + a ∗ M C h_l(MC)=1.5+a*MC hl(MC)=1.5+aMC, h r ( M C ) = 1.5 + b ∗ M C h_r(MC)=1.5+b*MC hr(MC)=1.5+bMC
  2. 二次多项式模型: h l ( M C ) = 1.5 + a 1 ∗ M C + a 2 ∗ M C 2 h_l(MC)=1.5+a_1*MC+a_2*MC^2 hl(MC)=1.5+a1MC+a2MC2, h r ( M C ) = 1.5 + b 1 ∗ M C + b 2 ∗ M C 2 h_r(MC)=1.5+b_1*MC+b_2*MC^2 hr(MC)=1.5+b1MC+b2MC2
  3. 指数模型: h l ( M C ) = 1.5 ∗ e a ∗ M C h_l(MC)=1.5*e^{a*MC} hl(MC)=1.5eaMC, h r ( M C ) = 1.5 ∗ e b ∗ M C h_r(MC)=1.5*e^{b*MC} hr(MC)=1.5ebMC

为了求上述模型中的常数,我们要求离群值的期望百分比为0.7%,这与正态分布下原箱线图的离群值百分比一致。

以线性模型举例,常数a,b应该满足 Q 1 − ( 1.5 + a ∗ M C ) ∗ I Q R = Q α Q_1-(1.5+a*MC)*IQR=Q_\alpha Q1(1.5+aMC)IQR=Qα, Q 3 + ( 1.5 + b ∗ M C ) ∗ I Q R = Q β Q_3+(1.5+b*MC)*IQR=Q_\beta Q3+(1.5+bMC)IQR=Qβ,其中 Q p Q_p Qp表示分布中的第p分位数, α = 0.0035 , β = 0.9965 \alpha=0.0035, \beta=0.9965 α=0.0035,β=0.9965。线性模型的修正函数可以改写为: Q 1 − Q α I Q R − 1.5 = a ∗ M C \frac{Q_1-Q_\alpha}{IQR}-1.5=a*MC IQRQ1Qα1.5=aMC Q β − Q 3 I Q R − 1.5 = b ∗ M C \frac{Q_\beta-Q_3}{IQR}-1.5=b*MC IQRQβQ31.5=bMC,然后可以用无截距的线性回归估计常数a和b。

二次模型和指数模型也可以利用同样的推导方法进行估计。例如,对于指数模型,经过转换,得到下面的线性形式:
l n ( 2 3 Q 1 − Q α I Q R ) = a ∗ M C l n ( 2 3 Q β − Q 3 I Q R ) = b ∗ M C ln(\frac{2}{3} \frac{Q_1-Q_{\alpha}}{IQR})=a*MC \\ ln(\frac{2}{3} \frac{Q_{\beta}-Q_3}{IQR})=b*MC ln(32IQRQ1Qα)=aMCln(32IQRQβQ3)=bMC

然后,作者从 Γ , χ 2 , F , P a r e t o , G g \Gamma, \chi^2, F, Pareto, G_g Γ,χ2,F,Pareto,Gg分布族中衍生出12605个分布的数据,用于训练出参数a,b。分布选取不极端倾斜的分布(保证medcouple<=0.6,因为很难找到简单的模型解决极端分布的情况),每个分布生成了10000个观测值。最终结果如下(这里只考虑对称和右偏的分布,y轴为 l n ( 2 3 Q β − Q 3 I Q R ) ln(\frac{2}{3} \frac{Q_{\beta}-Q_3}{IQR}) ln(32IQRQβQ3)):
在这里插入图片描述

可以看到指数模型拟合效果最好。

最终修正后的上下界为:
[ Q 1 − 1.5 ∗ e − 3.5 ∗ M C ∗ I Q R , Q 3 + 1.5 ∗ e 4 ∗ M C ∗ I Q R ] [Q_1-1.5*e^{-3.5*MC}*IQR, Q_3+1.5*e^{4*MC}*IQR] [Q11.5e3.5MCIQR,Q3+1.5e4MCIQR]

3. 总结

本文提出了一种进行偏度调整后的boxplot法,减弱了分布偏度的影响,在异常处理时是个不错的选择。

参考

[1] <AN ADJUSTED BOXPLOT FOR SKEWED DISTRIBUTIONS>

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
抱歉,之前的回答有误。`QSize` 类确实没有 `adjusted()` 方法。 为了解决这个问题,我们可以使用 `QRect` 类来代替 `QSize`,因为 `QRect` 包含了 `QSize` 以及位置信息。我们可以使用 `QRect` 的 `setSize()` 方法来设置大小,使用 `QRect` 的 `moveCenter()` 方法来移动中心点,从而实现缩放效果。 以下是修改后的示例代码: ```python from PyQt6.QtCore import QPropertyAnimation, QEasingCurve from PyQt6.QtGui import QRect from PyQt6.QtWidgets import QWidget, QApplication def animate_widget_size(widget: QWidget, target_width: int, target_height: int, duration: int): # 计算动画目标宽度和高度与当前宽度和高度的比例 width_ratio = target_width / widget.width() height_ratio = target_height / widget.height() # 创建 QPropertyAnimation 对象 animation = QPropertyAnimation(widget, b'geometry') animation.setDuration(duration) animation.setEasingCurve(QEasingCurve.OutQuad) # 设置动画的起始值和结束值 start_rect = widget.geometry() end_rect = QRect(start_rect) end_rect.setSize(QSize(target_width, target_height)) end_rect.moveCenter(start_rect.center()) animation.setStartValue(start_rect) animation.setEndValue(end_rect) # 开始动画 animation.start() if __name__ == '__main__': app = QApplication([]) w = QWidget() w.resize(200, 200) w.show() # 缩小 widget animate_widget_size(w, 100, 100, 1000) # 放大 widget animate_widget_size(w, 200, 200, 1000) app.exec() ``` 在这个示例中,我们计算了目标宽度和高度与当前宽度和高度的比例,用于计算缩放后的大小。我们创建了一个 `QPropertyAnimation` 对象,设置动画的起始值和结束值。`start_rect` 是 widget 的当前位置和大小,`end_rect` 是缩放后的位置和大小。我们使用 `QRect` 的 `setSize()` 方法来设置大小,使用 `QRect` 的 `moveCenter()` 方法来移动中心点。最后,启动动画。 这个示例中,我们使用了 `QRect` 代替了 `QSize`,解决了之前的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值