【问题标题】:Remove outlier from a single cell in R从 R 中的单个单元格中删除异常值
【发布时间】:2020-07-14 14:23:25
【问题描述】:

我是 R 的新手,但在删除一些异常值时遇到了问题。我有一个类似这样的数据框:

Item1   Item2   Item3
 4.05    3.9   3.6
 12      3.7   4
 4.01    3.8   4

我想要的结果应该类似于下表,即每列的异常值都被删除的表

Item1  Item2  Item3 
4.05    3.9    3.6
NA      3.7    4
4.01    3.8    4 

到目前为止,我已经编写了一个可以检测异常值的代码,但我坚持要删除它们,因为整个列都发生了变化,而不是单个值。

 find_outlier <- function(log_reaction_time) {
media <- mean(log_reaction_time)
devst <- sd(log_reaction_time)
result <-which(log_reaction_time < media - 2 * devst | log_reaction_time > media + 2 * devst)
log_reaction_time2 <- ifelse (log_reaction_time %in% result, NA, log_reaction_time)
}
apply(log_reaction_time, 2, find_outlier)

我想问题出在我将函数应用于列 (2) 的事实,因为我想找到列的异常值,但我只想删除相关值...

【问题讨论】:

  • 问题是你如何定义异常值,如果你使用分位数和IQR,你的第一列没有异常值。
  • 我没有使用分位数,而是删除了平均值 +/- 2 标准差之外的每个值。我认为我找到的代码可以正确检测异常值,我只想删除单元格而不是整个列。不过谢谢!
  • log_reaction_time 位于此数据框之外?
  • log_reaction_time 是数据帧的名称。所以我的想法是:我将函数定义为应用于 df,然后将其应用于不同的列。
  • 我很困惑 mean(log_reaction_time) 是每个条目的平均值还是一列的平均值?

标签: r outliers


【解决方案1】:

我们将使用相同的数据集来展示这一点:

#Data
df1 <- structure(list(Item1 = c(4.05, 12, 4.01), Item2 = c(3.9, 3.7, 
3.8), Item3 = c(3.6, 4, 4)), class = "data.frame", row.names = c(NA, 
-3L))

df1
  Item1 Item2 Item3
1  4.05   3.9   3.6
2 12.00   3.7   4.0
3  4.01   3.8   4.0

现在的功能:

#Function
find_outlier <- function(log_reaction_time) {
  media <- mean(log_reaction_time)
  devst <- sd(log_reaction_time)
  result <-which(log_reaction_time < media - 2 * devst | log_reaction_time > media + 2 * devst)
  log_reaction_time[result] <- NA
  return(log_reaction_time)
}

apply(df1, 2, find_outlier)

     Item1 Item2 Item3
[1,]  4.05   3.9   3.6
[2,] 12.00   3.7   4.0
[3,]  4.01   3.8   4.0

为了突出显示,Item1 的第二个值未设置为 NA,因为 mean(df1$Item1)=6.69sd(df1$Item1)=4.60。因此,当条件检查间隔时,您将拥有mean(df1$Item1)-2*sd(df1$Item1)=-2.51mean(df1$Item1)+2*sd(df1$Item1)=15.89,其中12 不在这些限制范围内。您必须定义其他条件来分配它NA

【讨论】:

    【解决方案2】:

    不太确定你想要哪个,但这里有一个 tidyverse 解决方案...

    
    library(dplyr)
    
    df %>% 
      mutate_all(function(x) ifelse(x < mean(x) - 2 * sd(x) | x > mean(x) + 2 * sd(x) , 
                                    NA_real_, 
                                    x))
    #> # A tibble: 3 x 3
    #>   Item1 Item2 Item3
    #>   <dbl> <dbl> <dbl>
    #> 1  4.05   3.9   3.6
    #> 2 12      3.7   4  
    #> 3  4.01   3.8   4
    
    media <- mean(as.matrix(df))
    devst <- sd(as.matrix(df))
    
    df %>% 
      mutate_all(function(x) ifelse(x < media - 2 * devst | x > media + 2 * devst , 
                                    NA_real_, 
                                    x))
    #> # A tibble: 3 x 3
    #>   Item1 Item2 Item3
    #>   <dbl> <dbl> <dbl>
    #> 1  4.05   3.9   3.6
    #> 2 NA      3.7   4  
    #> 3  4.01   3.8   4
    

    您的数据

    library(readr)
    df <- read_table("Item1   Item2   Item3
    4.05    3.9   3.6
    12      3.7   4
    4.01    3.8   4")
    

    【讨论】:

      【解决方案3】:

      使用dplyr,如果df 是您帖子中的第一个data.frame,则以下内容应该有效:

      library(dplyr)
      df %>%
        mutate(across(everything(), find_outlier)) -> new_df
      

      【讨论】:

        猜你喜欢
        • 2019-09-23
        • 1970-01-01
        • 1970-01-01
        • 2011-07-29
        • 1970-01-01
        • 2012-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多