我试图弄清楚如何在纵向数据集中对个体分组的观测进行组合.
我从这个优秀的答案开始,关于如何从变量的平均值中删除数据> 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 - 在此插入关于如何不应删除异常值的所有警告.这只是一个稳健性测试!)
我只想使用 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)