R函数找到列中异常值的百分比?

R function find the percentage of outliers in a column?

我需要创建一个函数来计算数据框列中离群值的百分比。对于离群值,我指的是与平均值相差超过 3 个标准差的任何数据点。

我查看了程序包 outlier 但这并没有解决我的问题,因为所有功能似乎都是为了寻找异常值而不是计算异常值。

有我可以使用的功能吗?

像这样,假设 x 是您的数据框中的一列?

set.seed(321)
x <- rnorm(10000)
x[x > mean(x) + 3*sd(x) | x < mean(x) - 3*sd(x)]
 [1]  3.135843 -3.006514  3.227549 -3.255502  3.065514  3.159309 -3.171849
 [8]  3.215432  3.120442  3.352662  3.574360  3.424063  3.126673 -3.024961
[15] -3.153842 -3.263268 -3.032526  3.179344 -3.605372

获取异常值的百分比

outli <- x[x > mean(x) + 3*sd(x) | x < mean(x) - 3*sd(x)]
length(outli) / length(x)
[1] 0.0019

并使其成为一个函数

find_outlier <- function(x, num=3) {
  mean(x > mean(x) + num*sd(x) | x < mean(x) - num*sd(x))
}


find_outlier(x)
[1] 0.0019

我觉得这个功能是你需要的:

outliersper <- function(x){
  length(which(x >  mean(x) + 3 * sd(x) | x < mean(x) - 3 * sd(x))  ) / length(x)
}

示例数据

#3 outliers here
df <- data.frame(col= c(1000,1000,1000,runif(100)))

#function
> outliersper(df$col)
[1] 0.02912621

验证

> length(which(df$col > (3 * sd(df$col))))
[1] 3
> 3/length(df$col)
[1] 0.02912621

这是一个 dplyr 方法:

library(dplyr)

# Fake data
set.seed(54)
dat = as.data.frame(replicate(5, rnorm(10000)))

set.seed(321)
dat$ExtraCol <- rnorm(10000)

# Number of SDs to be considered an outlier
n=3

在下面的代码中,. 是一个 "pronoun",意思是 "the current column of the data frame dat"。

# Percent outliers in every column
dat %>% 
  summarise_each(funs(sum(. > mean(.) + n*sd(.) | . < mean(.) - n*sd(.))/n()))

      V1     V2     V3     V4     V5 ExtraCol
1 0.0031 0.0039 0.0024 0.0028 0.0022   0.0019

还有很多方法可以select特定的列。

# Columns 1, 3, and 6
dat %>% 
  summarise_each(funs(sum(. > mean(.) + n*sd(.) | . < mean(.) - n*sd(.))/n()), 
                 c(1,3,6))

      V1     V3 ExtraCol
1 0.0031 0.0024   0.0019

# Columns whose name includes "Extra"
dat %>% 
  summarise_each(funs(sum(. > mean(.) + n*sd(.) | . < mean(.) - n*sd(.))/n()), 
                 matches("Extra"))

  ExtraCol
1   0.0019

# Select only numeric columns
dat$Letters = sample(LETTERS, 10000, replace=TRUE)

dat %>% 
  summarise_each(funs(sum(. > mean(.) + n*sd(.) | . < mean(.) - n*sd(.))/n()),
                 which(sapply(., is.numeric)))

      V1     V2     V3     V4     V5 ExtraCol
1 0.0031 0.0039 0.0024 0.0028 0.0022   0.0019