winsor2:离群值和异常值的缩尾处理
作者: 袁煜玲 (厦门大学)
目录
1. 异常值(离群值)
2. winsor2
2.1 winsor2 的简介
2.2 winsor2 的使用
2.3 多变量批量缩尾
2.4 分组缩尾与添加标签
3. 相关推文
1. 异常值(离群值)
在回归分析时,如果数据中存在异常值,很可能对回归结果产生非常大的影响,甚至扭曲真实结果。比较简单的理解,在算平均分数时,可能会去掉最高分和最低分;在计算一群人的平均身高时,会去掉超级高的人。
在回归中,几个异常值往往可能导致结果不真实,例如回归线扭曲。在下图中,异常值导致回归曲线偏移真实趋势,从而扭曲变量之间的真实关系。如果把左图右上方的异常值去掉,曲线斜率会大幅下降。因此,在连续变量回归之前,有必要先检查异常值,多数实证文章在回归之前,会先将连续变量进行 缩尾 或 截尾 处理。
本文介绍一个很好用的外部命令—— winsor2
2. winsor2
2.1 winsor2 的简介
winsor2
是由中山大学连玉君老师编写的 Stata 外部命令,能够非常方便的对连续变量进行缩尾或截尾处理。
2.2 winsor2 的使用
首先下载 winsor2
ssc install winsor2,replace
一般而言,在缩尾或者截尾之前,我们可以画个直方图,观察连续变量的数值分布情况。如果偏离正态分布非常远,可以考虑缩尾或者截尾处理。
histogram wage, ylabel(, angle(0)) xtitle("wage") name(fig1, replace)
使用 winsor2
进行缩尾处理:
sysuse nlsw88.dta, clearwinsor2 wage, cut(2.5 97.5)
其中,winsor2
后面跟着的是要缩尾的变量,cut(2.5 97.5)
表示将 wage 变量最小和最大的 2.5% 的值进行缩尾处理。所谓缩尾,就是将小于 2.5% 的值统一替换成 2.5% 的值,大于 97.5% 的值统一替换成 97.5% 的值。例如,如果最低的 2.5% 的工资是 5000,那么所有低于 5000 的工资都会被替换成 5000。默认情况下,winsor2
在缩尾后自动在旧变量名后加上 "_w",即生成缩尾后的新变量 wage_w。如果希望改变新变量的后缀,可以在 winsor2
命令行后面加 suffix()
,括号内填写新变量名称所要增加的后缀。如果希望缩尾后直接替换掉旧变量,而不生成新变量,则加上 replace
:
sysuse nlsw88.dta, clearwinsor2 wage, cut(2.5 97.5) replace //这是 winsor2 与 winsor 的主要区别
如果要进行截尾处理,只需在命令后面加上 trim
,即:
sysuse nlsw88.dta, clearwinsor2 wage, cut(2.5 97.5) trim
这样一来,就是所有位于 wage 最低 2.5% 和最高 2.5% 的观测值都被直接删除。但是,我们发现,wage 主要是右偏,因此我们可以对极大值进行截尾,而极小值则不截尾。截尾之后,默认生成新变量 wage_tr。
我们可以比较截尾前后变量的数值分布:
sysuse nlsw88.dta, clearwinsor2 wage, cut(0 97.5) trim //左端不截尾histogram wage, ylabel(, angle(0)) xtitle("wage") name(fig1, replace)histogram wage_tr, ylabel(, angle(0)) xtitle("wage_tr") name(fig2, replace)graph combine fig1 fig2
其中,wage 是截尾之前的变量,wage_tr 是截尾之后的变量,我们用 graph combine
将两幅图拼在一起。可以看到,在去掉极大的异常值后,变量分布更加均匀。
⏩ 2021 生存分析专题 (Survival Aanlysis)
⌚ 2021 年 4.24-25 (周六、周日)
⭐ 主讲:王存同教授 (中央财经大学)
⛪ 课程主页:https://gitee.com/lianxh/ST
我们可以对比截尾前后回归系数的差异:
reg wage hourseststo e1reg wage_tr hourseststo e2esttab e1 e2
可以看出,对 wage 截尾之后,Hours 对 wage 的回归系数有所下降,表明可能工资异常高的那一小部分人,每小时能赚的工资很高,因而把这最高的 2.5% 的样本删掉之后,剩下的样本每多工作一个小时所获取的工资就相对较少了。
-------------------------------------------- (1) (2) wage wage_tr--------------------------------------------hours 0.0872*** 0.0607*** (7.63) (8.15)
_cons 4.530*** 4.825*** (10.25) (16.78)--------------------------------------------N 2242 2186--------------------------------------------t statistics in parentheses* p<0.05, ** p<0.01, *** p<0.001
我们还可以对比一下缩尾和截尾的差别:
. sysuse nlsw88.dta, clear
. winsor2 wage, cut(0 97.5) trim //仅对右侧截尾
. winsor2 wage, cut(0 97.5) //仅对右侧缩尾
. histogram wage, ylabel(, angle(0)) xtitle("wage") name(fig1, replace)
. histogram wage_tr, ylabel(, angle(0)) xtitle("wage_tr") name(fig2, replace)
. histogram wage_w, ylabel(, angle(0)) xtitle("wage_w") name(fig3, replace)
. graph combine fig1 fig2 fig3
第一幅图是原变量 wage 的分布 第二幅图是截尾后的 wage 的分布 第三幅图是缩尾后的 wage 的分布
可以看出,右侧截尾是把右侧最高的 2.5% 的值直接截掉,而缩尾则是把这些值替换成 97.5% 分位数的值,因而在最右端多出了一个较长的柱体。
2.3 多变量批量缩尾
2.3.1 使用 Stata 的官方命令 winsor
:
一般而言,我们会有多个连续变量,此时第一反应可能是利用循环语句,实现批量缩尾处理:
sysuse nlsw88.dta, clearforeach v of varlist wage hours race{ winsor `v', gen(`v'_wi) p(0.025)}
使用 winsor
加循环语句,能够一次性对三个变量 wage 、hours 和 wage 进行缩尾处理,并生成三个缩尾后的新变量 wage_wi、hours_wi 和 race_wi。选项 p()
中填写该变量进行缩尾的数值百分比,例如对最高和最低 2.5% 的数值进行缩尾,则设定 p(0.025)
。默认进行两侧缩尾,如果只需要对最高值做缩尾处理,只需在命令行后面加上 highonly
,反之则加上 lowonly
。
2.3.2 winsor2
实现一行命令,批量缩尾:
以上使用 winsor
批量处理难免有点冗杂,有没有更简洁的方式呢?使用连老师编写的外部命令 winsor2
,无需循环,一行命令即可实现多变量的批量缩尾或截尾处理:
winsor2 wage hours race, cut(2.5, 97.5) //是不是很方便呢^.^?
2.4 分组缩尾与添加标签
winsor2
还有一个功能,就是分组缩尾,即将变量在分组内部分别进行缩尾。
例如,对变量 wage 进行分行业缩尾处理:
sysuse nlsw88.dta, clearwinsor2 wage hours race, cut(2.5, 97.5) by(ind)
如果希望缩尾或截尾后的变量自带“缩尾”或“截尾”标签,则在命令行后面加上 label
:
sysuse nlsw88.dta, clearwinsor2 wage hours race, cut(2.5, 97.5) by(ind) label
生成的新变量则都会自带标签,例如 wage_w 的标签是"hourly wage-Winsor(p00,p97.5)"。
更多关于离群值处理的信息,可以参考 吴世飞,连玉君,Stata:离群值!离群值?离群值!
3. 相关推文
Note:产生如下推文列表的命令为:
lianxh 离群值
安装最新版lianxh
命令:
ssc install lianxh, replace