Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在纵向数据集中winsorize(或删除单变量异常值)_R - Fatal编程技术网

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

如何在纵向数据集中winsorize(或删除单变量异常值),r,R,我试图弄清楚如何在纵向数据集中对个人分组的观察结果进行排序 我从如何从变量的平均值中删除大于2个标准差的数据开始。作者还有用地展示了如何在类别中实现这一点 我的用例略有不同:我有一个纵向数据集,我想删除那些随着时间的推移系统地显示为异常值的个体。我不想剔除受试者的极端观察结果,而是想将这些个体完全排除在外(整理数据),或者用切割值替换底部和顶部的2.5%(winsorizing,请参阅:) 例如,我的长格式数据可能如下所示: name time points MJ 1 998 MJ

我试图弄清楚如何在纵向数据集中对个人分组的观察结果进行排序

我从如何从变量的平均值中删除大于2个标准差的数据开始。作者还有用地展示了如何在类别中实现这一点

我的用例略有不同:我有一个纵向数据集,我想删除那些随着时间的推移系统地显示为异常值的个体。我不想剔除受试者的极端观察结果,而是想将这些个体完全排除在外(整理数据),或者用切割值替换底部和顶部的2.5%(winsorizing,请参阅:)

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

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
如果我想消除个体(
name
)中
点的极端观察,我的代码是:

do.call(rbind,by(df,df$name,function(x) x[!abs(scale(x$points)) > 2,]))
但我真正想做的是排除极端的个体(在本例中,
MJ
)。我该怎么做呢


(请注意——在这里插入关于如何不删除异常值的所有警告。这只是一个稳健性测试!)

我可以这样做:

means <- ddply(df, .(name), summarize, mean=mean(points))$mean
means <- mean(means)

upperBound <- 2

outlierTest <- ddply(df, .(name), summarize, outlier=ifelse(sum(points) / means > upperBound, 
TRUE, FALSE))

keep <- outlierTest$name[!outlierTest$outlier]

df <- df[df$name %in% keep, ]

意味着这可能不适合您的数据,但我将尝试一个通用的解决方案,让您开始思考。我建议使用稳健的统计数据,如中位数和中位数绝对贬值(MAD)来定义离群值。首先,您可以查看每个个体的异常点比例(与所有点相比):

df
成为您的数据帧

library(plyr)

med <- median(df$points)
md <- mad(df$points)
outlier.factor <- 2
daply(df, .(name), function(x) {sum(abs(x$points - m) > md * outlier.factor) / nrow(x)})
因此,
MJ
的所有分数都是异常值,而12.5%是所有其他个体的异常值


现在可以使用阈值选择要删除的个人。例如,对于正态分布的数据,您预计约有4.55%会落在中位数±2 x MAD的范围之外。

我只使用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)

测试好了,作为第一步,您需要定义汇总统计信息,根据该统计信息,您可以将某人识别为异常值。这是什么统计数据,以及它与其他值之间的距离应该被视为异常值?是的,这真的不应该是一个问题,除非我们不知道你将使用什么度量来定义MJ是极端的。@JoshO'Brien感谢你指出这一点;我将对我的问题作出澄清。最初的目标是进行95%的Winsorization,其中底部2.5%的个体和顶部2.5%的个体的观察值将替换为切割值。(见:)。然而,一个只“修剪”这些观察值的答案同样有用,因为问题在于识别而不是去除?我喜欢你的答案,但你如何用切点替换顶部和底部的2.5%?谢谢。我已经修改了我的答案来处理这种情况。第二个解决方案将更容易使用
pmin
pmax
有关如何使用pmin或pmax进行winsorizing的想法?我想到的是pmax(pmin(点,分位数,.95)),分位数(点,.05))。但接下来的技巧是将其作为新列插入数据帧中。思想?
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)
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))