一步去除异常值

Removing outliers in one step

我有一个数据集,其中由于输入错误而存在一些异常值。

我编写了一个函数来从我的数据框中删除这些异常值 (source):

remove_outliers <- function(x, na.rm = TRUE, ...) 
  {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)

  H <- 1.5 * IQR(x, na.rm = na.rm)
  y <- x
  y[x < (qnt[1] - H)] <- NA
  y[x > (qnt[2] + H)] <- NA
  y
  }

一旦我删除了这些离群值,数据集就被修改了。再次检查时,在某些情况下会显示一组新的异常值。

是否有任何一个阶段的方法可以去除所有可能的异常值?

我认为 "outlier" 是一个非常危险且具有误导性的术语。在许多情况下,它表示出于特定原因应从分析中排除的数据点。这样的原因可能是由于测量误差导致一个值超出了物理边界,而不是"it does not fit the other points around it"。

在这里,您根据实际数据的分布指定统计标准。先不说我在这里找不到合适的方法(因为这些数据可能是针对给定汽车精确测量的),当您将 remove_outliers 应用于数据时,该函数将确定异常值限制并设置数据点超出这些限制 NA.

## Using only column horsepower
dat <- read.csv("./cars.csv")

hp <- dat$Horsepower

## Calculates the boundaries like remove_outliers
calc.limits <- function(x, na.rm = TRUE) {
    qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm)
    H <- 1.5 * IQR(x, na.rm = na.rm)
    lwr <- qnt[1] - H
    upr <- qnt[2] + H
    c(lwr, upr)
}

> calc.limits(hp)
  25%   75% 
 -1.5 202.5 

这会产生一个具有 NA 值的新数据集。当您将 remove_outliers 应用于已经减少的数据集时,统计数据会有所不同,限制也会有所不同。因此,您将得到 "new" 个异常值(请参阅 Roland 的评论)。

hp2 <- remove_outliers(hp)

calc.limits(hp2)

> calc.limits(hp2)
25% 75% 
  9 185 

你可以想象这个事实:

plot(hp, ylim = c(0, 250), las = 1)

    abline(h = calc.limits(hp))

    abline(h = calc.limits(hp2), lty = 3)

实线表示原始数据的限制,虚线表示已经减少的数据。首先,您丢失了 10 个数据点,然后又丢失了 7 个。

> sum(is.na(hp2))
[1] 10

> sum(is.na(remove_outliers(hp2)))
[1] 17

总而言之,如果您没有充分的理由删除数据点,就不要这样做。

我通常建议不要删除异常值。考虑改用 robust 程序。他们会降低远离主要趋势的点的权重,但不会将它们从分析中移除。您还可以对数据进行可靠的转换,然后在分析中使用转换后的值。如果您仍想识别异常值,一个好的方法是 Median-MAD。这样效果更好,因为它使用的是中位数而不是均值,这使得它更加稳健。如果您有兴趣,我可以 post 我的 Med-MAD 测试代码。