如何在纵向数据集中进行winsorize(或删除单变量异常值)

roo*_*ody 12 r

我试图弄清楚如何在纵向数据集中对个体分组的观测进行组合.

我从这个优秀的答案开始,关于如何从变量的平均值中删除数据> 2个标准偏差.作者还有助于展示如何在类别中执行此操作.

我的用例略有不同:我有一个纵向数据集,我希望删除随着时间的推移,系统地显示为异常值的个体.我想要完全排除那些个体(修剪数据)或者用切割值替换底部和顶部2.5%(参见:http://en.wikipedia. org/wiki/Winsorising).

例如,我的长格式数据可能如下所示:

name time points
MJ   1    998
MJ   2    1000
MJ   3    998
MJ   4    3000
MJ   5    998
MJ   5    420
MJ   6    999
MJ   7    998
Lebron   1    9
Lebron   2    1
Lebron   3    3
Lebron   4    900
Lebron   5    4
Lebron   5    4
Lebron   6    3
Lebron   7    8
Kobe   1    2
Kobe   2    1
Kobe   3    4
Kobe   4    2
Kobe   5    1000
Kobe   5    4
Kobe   6    7
Kobe   7    9
Larry   1    2
Larry   2    1
Larry   3    4
Larry   4    2
Larry   5    800
Larry   5    4
Larry   6    7
Larry   7    9
Run Code Online (Sandbox Code Playgroud)

如果我想删除points个人(name)中的极端观察,我的代码将是:

do.call(rbind,by(df,df$name,function(x) x[!abs(scale(x$points)) > 2,]))
Run Code Online (Sandbox Code Playgroud)

但我真正想做的是排除极端的个人(在这种情况下MJ).我该怎么做呢?

(PS - 在此插入关于如何不应删除异常值的所有警告.这只是一个稳健性测试!)

use*_*808 4

我只想使用 dplyr:

test <- read.csv("test.csv", header=TRUE)
library(dplyr)

test <- test %.% 
  group_by(name) %.% 
  mutate(mean_points=mean(points))

cut_point_top <- quantile(test$mean_points, 0.95)
cut_point_bottom <- quantile(test$mean_points, 0.05)

test <- test %.% 
  group_by(name) %.% 
  mutate(outlier_top = (mean_points >= cut_point_top), 
         outlier_bottom = mean_points <= cut_point_bottom) %.%
  filter(!outlier_top & ! outlier_bottom)
Run Code Online (Sandbox Code Playgroud)

这会过滤掉平均得分位于前 2.5% 的 MJ 和位于后 2.5% 的 Larry。

如果您想将点变量替换为 2.5 个百分位数的分割点,只需删除最后一个过滤器语句,如下所示:

test <- test %.% 
  group_by(name) %.% 
  mutate(outlier_top = (mean_points >= cut_point_top), 
         outlier_bottom = mean_points <= cut_point_bottom) 

test$points <- ifelse(test$outlier_top, cut_point_top, 
                      ifelse(test$outlier_bottom, cut_point_bottom, test$points))
Run Code Online (Sandbox Code Playgroud)