与从数据集中移除异常值有关的问题(R)

时间:2018-12-05 17:15:27

标签: r machine-learning outliers

我用R语言编写的函数存在一些问题(我是这种语言的初学者)。此功能可删除数据集中的异常值:

removalOutlier <- function(data){
  q1 <- 0
  q2 <- 0
  q3 <- 0

 for(j in 1:(ncol(data)-1)){
   m <- length(data[,j])

   J<-0
   data<-data[order(data[,j]),]
   data<-as.matrix(data)
   print(data)
   q2 <- median(data[,j])

if((m %% 2) != 0){     
  q1 <- median(data[1:(((m+1)/2)-1),j]) #m dispari
  q3 <- median(data[(((m+1)/2)+1):m,j])
   } else {  
   q1 <- median(data[1:(m/2),j]) #m pari
   q3 <- median(data[(m+2)/2:m,j])     
  }

    iqr = q3-q1

    for(k in 1:(length(data[,j]))){
    print(data[k,j])

    if((data[k,j] > (q3+(1.5*iqr))) | (data[k,j] < (q1-(1.5*iqr))))

    {
     J[k]<-k
     data <- as.matrix(data) 
     }
     else 
     {J[k]<-0}        
   }

 data <- as.data.frame(data)

  for(z in 1:length(J)){
    if(J[z]!=0){

    data<-data.frame(data[-J[z],])
    } 
  }
 print (data)

}
data 
}

这是与数据集的第一列相关的有序输出。我将数据集的第一列除以四分位数,得出:Q1-1.5 * IQR = 117和Q3 + 1.5 * IQR = 3609。由于我有这些结果,因此函数应删除以下列表的最后三个示例:

     V1 V2     V3
45  852  2 179900
32 1000  1 169900
26 1100  3 249900
44 1200  3 299000
47 1203  3 239500
18 1236  3 199900
37 1239  3 229900
15 1268  3 259900
17 1320  2 299900
9  1380  3 212000
4  1416  2 232000
8  1427  3 198999
36 1437  3 249900
27 1458  3 464500
10 1494  3 242500
7  1534  3 314900
2  1600  3 329900
23 1604  3 242900
41 1664  2 368500
21 1767  3 252900
35 1811  4 285900
31 1839  2 349900
46 1852  4 299900
22 1888  2 255000
13 1890  3 329999
11 1940  4 239999
24 1962  4 259900
6  1985  4 299900
12 2000  3 347000
33 2040  4 314900
1  2104  3 399900
38 2132  4 345000
40 2162  4 287000
29 2200  3 475000
42 2238  3 329900
16 2300  4 449900
3  2400  3 369000
28 2526  3 469000
43 2567  4 314000
19 2609  4 499998
30 2637  3 299900
5  3000  4 539900
20 3031  4 599000
34 3137  3 579900
25 3890  3 573900
14 4478  5 699900
39 4515  4 549000

但会删除:

25 3890  3 573900
39 4515  4 549000

而不是:

14 4478  5 699900

我不明白为什么。当我通过检查第二列中的异常值时,我发现了它们并将其删除,没有任何问题。

2 个答案:

答案 0 :(得分:1)

此代码将根据您的IQR逻辑删除最后3行

bound <- quantile(df$V1, c(.25, .75)) + c(-1, 1)*1.5*IQR(df$V1)
out <- subset(df, V1 > bound[1] & V1 < bound[2])

检查结果:

nrow(df) - nrow(out)
# [1] 3

data.table::fsetdiff(df, out)
#      V1 V2     V3
# 1: 3890  3 573900
# 2: 4478  5 699900
# 3: 4515  4 549000

使用的数据:

df <- data.table::fread('
     V1 V2     V3
45  852  2 179900
32 1000  1 169900
26 1100  3 249900
44 1200  3 299000
47 1203  3 239500
18 1236  3 199900
37 1239  3 229900
15 1268  3 259900
17 1320  2 299900
9  1380  3 212000
4  1416  2 232000
8  1427  3 198999
36 1437  3 249900
27 1458  3 464500
10 1494  3 242500
7  1534  3 314900
2  1600  3 329900
23 1604  3 242900
41 1664  2 368500
21 1767  3 252900
35 1811  4 285900
31 1839  2 349900
46 1852  4 299900
22 1888  2 255000
13 1890  3 329999
11 1940  4 239999
24 1962  4 259900
6  1985  4 299900
12 2000  3 347000
33 2040  4 314900
1  2104  3 399900
38 2132  4 345000
40 2162  4 287000
29 2200  3 475000
42 2238  3 329900
16 2300  4 449900
3  2400  3 369000
28 2526  3 469000
43 2567  4 314000
19 2609  4 499998
30 2637  3 299900
5  3000  4 539900
20 3031  4 599000
34 3137  3 579900
25 3890  3 573900
14 4478  5 699900
39 4515  4 549000
')[, -1]

答案 1 :(得分:1)

以下功能可根据问题的标准删除异常值,但结果与OP的结果不同。

removalOutlier2 <- function(data){
  f <- function(x){
    iqr <- IQR(x, na.rm = TRUE)
    qq <- quantile(x, c(1, 3)/4)
    lims <- qq + c(-1, 1)*1.5*iqr
    out <- which(x < lims[1] | lims[2] < x)
    x[out] <- median(x, na.rm = TRUE)
    x
  }
  data[] <- lapply(data, f)
  data
}

df2 <- removalOutlier2(data)

编辑。

函数的结果与answerIceCreamToucan中的结果一致。