【问题标题】:How to replace outliers with the 5th and 95th percentile values in R如何用R中的第5个和第95个百分位值替换异常值
【发布时间】:2012-10-31 15:20:01
【问题描述】:

我想将我相对较大的 R 数据集中所有取值高于 95 和低于第 5 个百分位的值分别替换为这些百分位值。我的目标是避免简单地从数据中完全裁剪这些异常值。

任何建议都将不胜感激,我在其他任何地方都找不到有关如何执行此操作的任何信息。

【问题讨论】:

  • 除了回答这个问题需要更多详细信息之外,您确定要这样做吗?一个相对较大的数据集,比如 100 个数字,如果没有异常值,则在第 5 个百分位以下有 5 个值,在第 95 个百分位以上有 5 个值。
  • 在采取这些措施时要格外小心,因为您正在彻底改变数据集的统计数据。这是否有效取决于您试图从数据中获得什么,以及数据的分布(例如正态分布)。
  • @RobS 小心使用= 作为赋值运算符。 <- 可以复合,但=不能
  • 我几乎总是使用=,而且我很少遇到麻烦。只有在像system.time(bla <- spam()) 这样的电话中,<- 是强制性的。
  • Bobbo,缺少的细节包括模型是什么以及如何定义百分位数;您是否想要从数据中得出的经验截止值或从模型中得出的截止值以及该模型是什么;特别是您希望如何替换数据点...使用模型参数替换为随机值?...其他形式的插补?回到终点?此外,您所做的事情本身并不能测试稳健性。这将需要添加其他内容。

标签: r dataset outliers quantile


【解决方案1】:

有更好的方法来解决这个问题。离群值不是超过 95% 或低于 5% 的任何点。相反,如果异常值低于第一个四分位数 - 1.5·IQR 或高于第三个四分位数 + 1.5·IQR,则会被视为异常值。
This website will explain in more thoroughly

To know more about outlier treatment refer here

capOutlier <- function(x){
   qnt <- quantile(x, probs=c(.25, .75), na.rm = T)
   caps <- quantile(x, probs=c(.05, .95), na.rm = T)
   H <- 1.5 * IQR(x, na.rm = T)
   x[x < (qnt[1] - H)] <- caps[1]
   x[x > (qnt[2] + H)] <- caps[2]
   return(x)
}
df$colName=capOutlier(df$colName)
Do the above line over and over for all of the columns in your data frame

【讨论】:

  • 这是对异常值的严格定义。您是否将异常值定义定义为低于 20%/高于 80%+(如您所定义)或低于 5%/高于 95%+(作为 OP)是任意的;什么有效取决于您的问题和数据。
  • 我没有将其定义为低于 20% 或高于 80%。我使用了一个常见的异常值定义,可能会在统计类的介绍中使用。小于第一个四分位数 - 1.5 * 四分位数范围或高于第三个四分位数 + 1.5 * 四分位数范围被视为异常值。四分位距(IQR)是第一个四分位数和第三个四分位数之间的范围(数据的中间 50%)。
  • 这不是异常值的“常见”定义。这是一个任意的
  • 如果你在大学里上过 101 的统计课,他们会给你这个异常值的定义。检查我的答案中的网站。对于异常值还有其他定义,但这是最基本和最常用的定义。而且,我发布的定义比问题中给出的定义更准确。如果您有数据 (.99998,1,1,1,1,1,1,1,1.0001),那么如果您使用问题中描述的异常值分类方法,0.99998 和 1.0001 将被错误地分类为异常值。
【解决方案2】:

你可以在一行代码中使用squish()

d2 <- squish(d, quantile(d, c(.05, .95)))



在 scales 库中,查看 ?squish?discard

#--------------------------------
library(scales)

pr <- .95
q  <- quantile(d, c(1-pr, pr))
d2 <- squish(d, q)
#---------------------------------

# Note: depending on your needs, you may want to round off the quantile, ie:
q <- round(quantile(d, c(1-pr, pr)))

示例:

d <- 1:20
d
# [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20


d2 <- squish(d, round(quantile(d, c(.05, .95))))
d2
# [1]  2  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 19

【讨论】:

  • 不错。或者你可以将 squish 加入你自己的函数中。 cap &lt;- function(x, low, high) pmin(high, pmax(low, x))
【解决方案3】:

我用这段代码来得到你需要的东西:

qn = quantile(df$value, c(0.05, 0.95), na.rm = TRUE)
df = within(df, { value = ifelse(value < qn[1], qn[1], value)
                  value = ifelse(value > qn[2], qn[2], value)})

其中df 是您的data.frame,value 是包含您的数据的列。

【讨论】:

  • 感谢您的回答,您的和上面的都可以正常工作
【解决方案4】:

这样就可以了。

fun <- function(x){
    quantiles <- quantile( x, c(.05, .95 ) )
    x[ x < quantiles[1] ] <- quantiles[1]
    x[ x > quantiles[2] ] <- quantiles[2]
    x
}
fun( yourdata )

【讨论】:

  • 谢谢你,像梦一样工作。我是这个网站的新手,有什么办法可以给你代表或其他答案吗?
  • 您可以提出答案并接受(您已经接受了)。请参阅stackoverflow.com/faq,如果您阅读全部内容,也会给您一个徽章
  • 上面的 sn-p 也会用分位数替换 NAs(如果有的话)!
  • 检查来自 pandas pandas.pydata.org/docs/reference/api/… 的 .clip 函数以及
猜你喜欢
  • 2019-12-26
  • 2011-10-10
  • 2023-02-24
  • 1970-01-01
  • 2021-01-12
  • 2021-02-07
  • 1970-01-01
  • 2017-09-15
  • 2023-03-27
相关资源
最近更新 更多