如何重复Grubbs测试并标记异常值

时间:2014-04-03 12:02:10

标签: r outliers

我想反复将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

2 个答案:

答案 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()

Outlier Histogram

答案 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>