如何删除数据帧各列中的离群值(离均值3个标准差)

时间:2019-03-25 11:38:32

标签: r

我有一个包含参与者IDS的数据集,每个参与者都有17种不同的度量。

我需要删除离均值3个标准差的离群值。这需要针对每个列分别进行。

到目前为止,通过使用下面的代码,我设法将NA添加到每列的异常值列中,但这并没有多大帮助,因为我需要能够将NA和其余的列添加到该列中或只是删除离群值

理想情况下,我想获取一个看起来像这样的文件:

ID measure1 measure2 ....measure17
1  10897                  64436
2  184658    1739473
3            75758
4  746483    4327349      3612638
5  6444      36363        46447

到目前为止我使用的代码:

phenotypes <- colnames(imaging_data_kept[,2:ncol(imaging_data_kept)])

 for (i in phenotypes){
  Min <- mean(imaging_data_kept[[i]]) - (3*sd(imaging_data_kept[[i]]))
  Max <- mean(imaging_data_kept[[i]]) + (3*sd(imaging_data_kept[[i]]))  
  imaging_data_kept[[paste0(i,"_outliers")]] <- imaging_data_kept[[i]] < 
  Min | imaging_data_kept[[i]] > Max
 }

样本数据:

SubjID M1 M2 M3 M4 M5 
1000496 14898.1 9172 4902 5921.9 1428.2 
1001121 5420.7 2855.5 4144 732.1 4960.2 
1001468 7478.8 3401.4 5143.6 1106.5 4355.5 
1004960 11316.4 8460.1 3953.4 5682.2 1717 
1005040 15052.7 6362.8 3145.2 4593 1214.5  
1005677 17883.3 6705.1 3943.5 4993.1 1373.1 
1006128 6260.8 4274.6 5865 2002.3 4727.1 
1006694 9292.8 3389.9 5141.6 1246.6 4135.7 
1009080 10391.3 8372.1 2921.8 4008.6 860.4 
1010482 9381.5 2743.4 4526.5 1160.4 3655.1 
1011508 15598.5 7365.7 4279.4 6274.1 1757.1 

2 个答案:

答案 0 :(得分:1)

我建议使用pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_AUTONEGO_EN); -函数来计算离群值。您可以通过boxplot()boxplot对象中访问它们,也可以通过boxplot$out获取分位数。接下来我要做什么。

但是请注意,箱线图不会以3个标准差来计算离群值,而是分别以boxplot$statsQ1 - 1.5*IQR来计算。

Q3 + 1.5*IQR

此代码计算每一列的晶须范围,将 library(dplyr) # for the pipe operators #creating sample data df <- data.frame("var1" = c(-20.32, -15.29, rnorm(5,1,1), 11.23, 20.45), "var2" = c(-12.43, -3.12, rnorm(5, 1,1), 10.75, 18.11)) #looks like that > df var1 var2 1 -20.3200000 -12.4300000 2 -15.2900000 -3.1200000 3 0.9950276 1.2645415 4 1.7022687 0.8313770 5 1.8828154 -0.7459769 6 1.2299670 0.5053378 7 0.2749259 2.0239793 8 11.2300000 10.7500000 9 20.4500000 18.1100000 #remove outliers nooutliers <- lapply(df, function(x) boxplot(df, plot = FALSE)) %>% lapply(`[`, "stats") %>% lapply(range) %>% mapply(function (x,y) !between(x, y[1], y[2]), df, .) %>% as.data.frame %>% mapply(function(x,y) {y[x] <- NA; y}, y = df, x = .) #looks like this now > nooutliers var1 var2 [1,] NA NA [2,] NA -3.1200000 [3,] 0.9950276 1.2645415 [4,] 1.7022687 0.8313770 [5,] 1.8828154 -0.7459769 [6,] 1.2299670 0.5053378 [7,] 0.2749259 2.0239793 [8,] NA NA [9,] NA NA 分配给该范围之外的所有值,并返回一个矩阵。

我想这就是你想要的。

更新:具有3个标准偏差:

NA

这采用您的异常值定义。

答案 1 :(得分:0)

这将用NA代替均值大于3 SD的值:

dd[,-1] <- lapply(dd[,-1],
      function(x) replace(x,abs(scale(x))>3,NA))

scale()函数计算(x-mean(x))/sd(x)abs(scale(x))>3应该是不言自明的; replace()用指示的值替换一组指定的索引。)

如果要删除任何包含异常值的所有行,则可以使用na.omit(dd)

您提供给我们的示例数据似乎没有任何异常值(根据您的定义)-我添加了一些。


dd <- read.table(header=TRUE,
                 colClasses=c("character",rep("numeric",5)),
                 text="
SubjID M1 M2 M3 M4 M5 
1000496 14898.1 9172 4902 5921.9 1428.2 
1001121 5420.7 2855.5 4144 732.1 100000
1001468 7478.8 3401.4 5143.6 1106.5 4355.5 
1004960 11316.4 8460.1 3953.4 5682.2 1717 
1005040 15052.7 6362.8 3145.2 4593 1214.5  
1005677 17883.3 6705.1 100000 4993.1 1373.1 
1006128 6260.8 4274.6 5865 2002.3 4727.1 
1006694 9292.8 3389.9 5141.6 1246.6 4135.7 
1009080 10391.3 8372.1 2921.8 4008.6 860.4 
1010482 9381.5 2743.4 4526.5 1000000 3655.1 
1011508 15598.5 7365.7 4279.4 6274.1 1757.1
")