一步去除异常值
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 测试代码。
我有一个数据集,其中由于输入错误而存在一些异常值。
我编写了一个函数来从我的数据框中删除这些异常值 (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 测试代码。