使用箱线图法从数据框中删除异常值

时间:2019-03-21 09:51:45

标签: r outliers

我有一个大约15个变量的数据框。我必须从变量中删除离群值。

在网上学习完一个教程之后,我正在使用箱线图方法去除异常值。我正在使用一种堆叠的方式从数据帧中逐个删除异常值,直到处理完所有数据为止。

这是我的代码。我的问题是,这是消除异常值或如何改进代码的好方法。

#removong outliers from the columns
outliers <- boxplot(outlier_H_rem$var1, plot=FALSE)$out
if(length(outliers) == 0){ outlier_H_rem1<-outlier_H_rem
boxplot(outlier_H_rem1$var1)} else { 
outlier_H_rem1<-outlier_H_rem[-which(outlier_H_rem$var1 %in% outliers),]
var1<-outlier_H_rem1$var1}
boxplot(outlier_H_rem1$var1)

outliers <- boxplot(outlier_H_rem1$var2, plot=FALSE)$out
if(length(outliers) == 0){ outlier_H_rem2<-outlier_H_rem1
boxplot(outlier_H_rem2$var2)} else { 
outlier_H_rem2<-outlier_H_rem1[-which(outlier_H_rem1$var2 %in% outliers),]
moisture2<-outlier_H_rem2$var2}
boxplot(outlier_H_rem2$var2)

outlier_H_rem是我每次与下一个var一起测试的堆栈数据帧outlier_H_rem1 $ var1,outlier_H_rem2 $ var2,outlier_H_rem3 $ var3直到最后一个var。 outlier_H_rem15 $ var15是使用所有变量处理的最后一个堆栈数据帧。

2 个答案:

答案 0 :(得分:0)

我可以从您对@Humpelstielzchen的回答中了解到,您希望将变量作为单独的向量进行工作,因此我将根据这一点进行回答,但是请记住,后续变量的合并可能很困难,因为您会丢失变量的位置顺序当将它们提取为单个向量然后删除一些观察值时,这些值。

在下面的示例中,我创建了一些示例数据来阐明此问题。请注意,var3没有异常值。您以后如何合并数据(它们将具有不同的长度)?同样,即使在异常值移除后var1和var2都以11个观测结果结束,向量中的最后一个位置仍来自原始数据中的位置11和12。

鉴于您对此还可以,那么您的方法将起作用。我已经对您的代码发表了一些意见。

library(tidyverse)

set.seed(1)

outlier_H_rem <- tibble(
  var1 = rnorm(10, 0, 1),
  var2 = rnorm(10, 0, 1),
  var3 = rnorm(10, 0, 1)) %>% 
  #Introduce outliers
  rbind(c(5, 0, 0), c(0,7, 0))

outlier_H_rem

#removeing outliers from the columns
outliers <- boxplot(outlier_H_rem$var1, plot=FALSE)$out

if(length(outliers) == 0){ 
  outlier_H_rem1 <- outlier_H_rem
  #boxplot(outlier_H_rem1$var1) - This line is irrelevant as you create the plot again after the if else call
  } else { 
  outlier_H_rem1 <- outlier_H_rem[-which(outlier_H_rem$var1 %in% outliers),]
  var1 < -outlier_H_rem1$var1 #What is the purpose of this line?
  }

boxplot(outlier_H_rem1$var1)

答案 1 :(得分:0)

我可以建议一种稍微不同的方法。

将您的数据从宽格式转换为长格式,然后使用分位数和分位数范围计算离群值。

然后过滤掉异常值,然后变换回宽幅形式。删除带有异常值的行将为您带来理想的结果

基于@Steen Harsted

library(tidyverse)

set.seed(1)

outlier_H_rem <- tibble(
  var1 = rnorm(10, 0, 1),
  var2 = rnorm(10, 0, 1),
  var3 = rnorm(10, 0, 1)) %>% 
  #Introduce outliers
  rbind(c(5, 0, 0), c(0,7, 0))

outlier_H_rem

# A tibble: 12 x 3
var1    var2    var3
<dbl>   <dbl>   <dbl>
  1 -0.626  1.51    0.919 
2  0.184  0.390   0.782 
3 -0.836 -0.621   0.0746
4  1.60  -2.21   -1.99  
5  0.330  1.12    0.620 
6 -0.820 -0.0449 -0.0561
7  0.487 -0.0162 -0.156 
8  0.738  0.944  -1.47  
9  0.576  0.821  -0.478 
10 -0.305  0.594   0.418 
11  5      0       0     
12  0      7       0 

outlier_H_rem %>% 
  # Collect dat in tidy form
  tidyr::gather("Feature", "Value", everything()) %>%
  ggplot2::ggplot(aes(x=Feature, y=Value)) +geom_boxplot()

stackblitz

现在是如何使用tidyverse工具识别异常值

outlier_H_rem %>% 
  # Collect data in tidy form
  tidyr::gather("Feature", "Value", everything()) %>% 
  # Group by "Feature" and calculate outliers using iqr and quantiles
  # Also adding a row counter
  group_by(Feature) %>% 
  mutate(r=1:n()) %>%
  mutate(q1 = quantile(Value,probs=0.25),
         q3 = quantile(Value,probs=0.75),
         iqr = IQR(Value),
         outlier = if_else((q1-1.5*iqr)>Value | (q3+1.5*iqr)<Value, TRUE, FALSE)) %>% 
  # Filter out the ouliers
  filter(!outlier) %>% 
  # deselect calculated rows
  select(-q1, -q3, -iqr, -outlier) %>%
  # Spread the results again. 
  # optionally remove rows with rows with NA (contained outliers) using na.omit()
  spread(Feature, Value) %>% 
  # remove row counter
  select(-r)

# A tibble: 12 x 3
var1     var2     var3
*   <dbl>    <dbl>    <dbl>
  1  -0.626   1.51     0.919 
2   0.184   0.390    0.782 
3  -0.836  -0.621    0.0746
4   1.60   NA       NA     
5   0.330   1.12     0.620 
6  -0.820  -0.0449  -0.0561
7   0.487  -0.0162  -0.156 
8   0.738   0.944   NA     
9   0.576   0.821   -0.478 
10  -0.305   0.594    0.418 
11  NA       0        0     
12   0      NA        0