我想反复将Grubbs测试应用于一组数据,直到它不再找到异常值。我希望标记异常值而不是删除异常值,以便我可以将数据绘制为直方图,异常值为不同颜色。我已经使用了异常值包中的grubbs.test来手动识别异常值,但无法弄清楚如何循环它们并成功标记它们。我的目标输出类似如下:
X Outlier
152.36 Yes
130.38 Yes
101.54 No
96.26 No
88.03 No
85.66 No
83.62 No
76.53 No
74.36 No
73.87 No
73.36 No
73.35 No
68.26 No
65.25 No
63.68 No
63.05 No
57.53 No
答案 0 :(得分:19)
看起来你需要一个简短的功能来做你想做的事情:
library(outliers)
library(ggplot2)
X <- c(152.36,130.38,101.54,96.26,88.03,85.66,83.62,76.53,
74.36,73.87,73.36,73.35,68.26,65.25,63.68,63.05,57.53)
grubbs.flag <- function(x) {
outliers <- NULL
test <- x
grubbs.result <- grubbs.test(test)
pv <- grubbs.result$p.value
while(pv < 0.05) {
outliers <- c(outliers,as.numeric(strsplit(grubbs.result$alternative," ")[[1]][3]))
test <- x[!x %in% outliers]
grubbs.result <- grubbs.test(test)
pv <- grubbs.result$p.value
}
return(data.frame(X=x,Outlier=(x %in% outliers)))
}
这是输出:
grubbs.flag(X)
X Outlier
1 152.36 TRUE
2 130.38 TRUE
3 101.54 FALSE
4 96.26 FALSE
5 88.03 FALSE
6 85.66 FALSE
7 83.62 FALSE
8 76.53 FALSE
9 74.36 FALSE
10 73.87 FALSE
11 73.36 FALSE
12 73.35 FALSE
13 68.26 FALSE
14 65.25 FALSE
15 63.68 FALSE
16 63.05 FALSE
17 57.53 FALSE
如果您想要一个不同颜色的直方图,您可以使用以下内容:
ggplot(grubbs.flag(X),aes(x=X,color=Outlier,fill=Outlier))+
geom_histogram(binwidth=diff(range(X))/30)+
theme_bw()
答案 1 :(得分:9)
Sam Dickson的answer很棒,但是如果你达到一个点,除了两个值之外的所有值都被标记为异常值,或者你只是在第一个地方开始使用三个值(grubbs.test()如果输入向量中只有两个值,则不会返回p值。
我为此偶然事件添加了一个断点到while循环,如果发生这种情况,它也会发出警告。此外,当您使用少于两个输入值启动时,它将抛出信息性错误。
grubbs.flag <- function(x) {
outliers <- NULL
test <- x
grubbs.result <- grubbs.test(test)
pv <- grubbs.result$p.value
# throw an error if there are too few values for the Grubb's test
if (length(test) < 3 ) stop("Grubb's test requires > 2 input values")
while(pv < 0.05) {
outliers <- c(outliers,as.numeric(strsplit(grubbs.result$alternative," ")[[1]][3]))
test <- x[!x %in% outliers]
# stop if all but two values are flagged as outliers
if (length(test) < 3 ) {
warning("All but two values flagged as outliers")
break
}
grubbs.result <- grubbs.test(test)
pv <- grubbs.result$p.value
}
return(data.frame(X=x,Outlier=(x %in% outliers)))
}
当然,如果你只有三个数据点,但是我不了解你的业务,那么可能做出离群值测试没有多大意义。 / p>