【问题标题】:After deletion: outliers near maximum, remaining in R boxplot删除后:离群值接近最大值,保留在 R 箱线图中
【发布时间】:2020-08-23 06:51:56
【问题描述】:

在 R 中创建一个函数后,该函数应该返回一个用 NA 代替某些数据的异常值向量,我得到的异常值保持在最大值附近:

kill_outliers <- function(data, na.rm=TRUE){
  q <- quantile(data, probs=c(0.25, 0.75), na.rm=na.rm)
  killed <- data
  intq <- 1.5 * IQR(data, na.rm=na.rm)
  killed[x < (q[1]-intq)] <- NA
  killed[x > (q[2]+intq)] <- NA
  killed
}

使用此函数后boxplot(killed)显示:

为什么会有异常值?我试过了:

killed[x > (q[2] + intq)] <- NA

假设这是小于或等于的问题,但它并没有改变任何东西。

(q[2] + intq) == 216.87,删除后排序数据集中的最后一个值是216.16,应该适合。 另外,我不明白为什么,当我使用第三分位数(q[3] + intq) 时,它根本没有排除任何异常值......

编辑

如机器所示,问题在于使用新 IQR 创建新数据集。因此我得出结论, boxplot() 为每个数据集创建了一个估计 IQR 的新图。附加问题:有没有办法将新数据集拟合到由箱线图创建的先前图,以便将值拟合到以前的分位数?

【问题讨论】:

  • 不是一个直接的答案,但如果您更改数据只是为了绘制箱线图而不显示异常值,您可以通过简单地使用 boxplot(x,outline=F) 更轻松地实现这一点

标签: r outliers


【解决方案1】:

@machine 是对的,删除“异常值”会改变分布及其参数。

我想补充一点,如果没有严重的理由,绝不应该删除异常值。一个点超过箱线图中胡须的事实不是这样的原因。少量的接近值是完全正态的,而大量这样的点可以被认为是非正态分布的指标。在这种情况下,我更愿意避免使用异常值一词并以不同的方式称呼它,例如极端值。

set.seed(765)
boxplot(rnorm(100))    # normal distribution
boxplot(rt(100, df=3)) # t distribution with long tails
boxplot(rlnorm(100))   # lognormal, skewed

所有这些示例都不符合去除异常值的条件。另一种情况是,当某些点由大于通常方差或测量误差的单独“过程”创建时。

boxplot(c(rnorm(100), 7))

在这里,可以应用异常值测试,例如outlierTest 来自包装 car 并带有 Bonferroni 校正:

library(car)
outlierTest(lm(x ~ 1))

很明显,这样的测试不能重复应用。

搜索 crossvalidated,您会发现几篇关于异常值问题的好文章,例如whether to delete cases that are flagged as outliers ...is it cheating to drop the outliers based on the boxplot ...

【讨论】:

  • 我同意你的看法。我试图从 Stack Overflow 的角度回答这个问题,因此忽略了统计问题。根据 OP 实际想知道的内容,这实际上可能更适合交叉验证。
  • 我不想重新发布已在 CV 上回答的问题,正如 tpetzoldt 所引用的。但是,这些答案主要与拟合回归线有关。我的目标是置信区间呢?是否仍然建议保存异常值? (或者我的问题对于这个网站来说太简历了?)编辑:我真的很感谢你的回答 :) 他们非常有帮助
  • 大体原理是一样的。平均值的置信区间与斜率为零的回归截距相当,即所谓的空模型:lm(y ~ 1)
【解决方案2】:

您的函数会删除异常值,因此,您会使用 new IQR 获得变量的新分布。对于新的 IQR,其他值可能是与原始变量的 IQR 无关的异常值(因此不会被杀死)。因此,只要存在异常值,您就需要一次又一次地重新运行函数。

这是一个只要有异常值就运行的代码:

kill_outliers <- function(data, na.rm=TRUE){
q <- quantile(data, probs=c(0.25, 0.75), na.rm=na.rm)
  intq <- 1.5*IQR(data, na.rm=na.rm)
intq_low <- q[1]-intq
intq_high <- q[1]+intq

killed <- data
while(any(killed < intq_low, na.rm=TRUE) | any(killed > intq_high, na.rm= TRUE)){ 
  killed[killed<intq_low] <- NA
  killed[killed>intq_high] <- NA

q <- quantile(killed, probs=c(0.25, 0.75), na.rm=na.rm)
  intq <- 1.5*IQR(killed, na.rm=na.rm)
intq_low <- q[1]-intq
intq_high <- q[1]+intq
}
killed
}

boxplot(kill_outliers(rnorm(9999)))

此外,在您的函数中有一个未定义的 objext x 可能在您的环境中并且也会导致问题。

【讨论】:

  • 但是,如果我反复删除异常值,好像我改变了数据,不是吗?对我来说,太多的删除意味着对数据的太多更改。如果我想尽可能精确地坚持数据,运行第一次删除并向箱线图添加评论是否可以接受,删除异常值会导致 IQR 发生变化,但我想坚持第一个 IQR ?
  • @Question 这是一个新问题。我的意见:当然你会改变你的数据,如果我们删除一次异常值也是如此。发布最重要的事情是准确报告您如何转换数据。我想这取决于您处理异常值的方式。如果我的帖子按现状回答了问题,请考虑将其标记为已回答,因为这就是本网站的工作方式。
猜你喜欢
  • 1970-01-01
  • 2023-03-13
  • 2021-05-16
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
相关资源
最近更新 更多