【问题标题】:How to get outliers for all the columns in a dataframe in r如何获取r中数据框中所有列的异常值
【发布时间】:2018-02-24 13:53:38
【问题描述】:

我正在研究通用函数,它将获取数据帧并返回数据帧中每个变量的所有异常值,然后将其删除。

 outliers <- function(dataframe){
   dataframe <- select_if(dataframe, is.numeric)
   for(i in 1:length(dataframe)){
   paste(names(dataframe)[i]) <- boxplot.stats(names(dataframe)[i])$out)

  }
}

我想输出各个变量中的所有异常值,然后最终从数据框中删除所有异常值。

我可以通过关注一个一个删除

Clean_Data[!Clean_Data$House_Price %in% boxplot.stats(Clean_Data$House_Price)$out,]

您可以从Clean_Data = read.csv('http://ucanalytics.com/blogs/wp-content/uploads/2016/09/Regression-Clean-Data.csv')获取数据

【问题讨论】:

  • 那么问题是什么?
  • 我的功能不起作用。我想输出不同向量中所有变量的所有异常值。
  • 你能提供一个可重现的例子吗?数据、使用的包、期望的输出...
  • 我已经添加了数据。在输出中,我希望将所有数值变量及其各自的异常值放在一个单独的向量中

标签: r


【解决方案1】:

我们通过仅选择 numeric 列 (select_if) 创建一个函数,遍历这些列 (map) 并对不是异常值的元素进行子集化。这将作为listvectors 输出。

library(dplyr)
library(tidyr)
library(purrr)
outlierremoval <- function(dataframe){
 dataframe %>%
      select_if(is.numeric) %>% #selects on the numeric columns
      map(~ .x[!.x %in% boxplot.stats(.)$out]) #%>%
      # not clear whether we need to output as a list or data.frame
      # if it is the latter, the columns could be of different length
      # so we may use cbind.fill
      # { do.call(rowr::cbind.fill, c(., list(fill = NA)))}

 }

outlierremoval(Clean_Data)

如果我们想保留所有其他列,则使用 map_if 并在末尾附加 NA 使用 cbind.fill 创建 data.frame 输出。但是,这也会导致每列中的行位置根据异常值的数量发生变化

outlierremoval <- function(dataframe){
 dataframe %>%          
       map_if(is.numeric, ~ .x[!.x %in% boxplot.stats(.)$out]) %>%
       { do.call(rowr::cbind.fill, c(., list(fill = NA)))} %>%
       set_names(names(dataframe))
     


}
res <- outlierremoval(Clean_Data)
head(res)
#  X Observation Dist_Taxi Dist_Market Dist_Hospital Carpet Builtup      Parking City_Category Rainfall House_Price
#1 1           1      9796        5250         10703   1659    1961         Open         CAT B      530     6649000
#2 2           2      8294        8186         12694   1461    1752 Not Provided         CAT B      210     3982000
#3 3           3     11001       14399         16991   1340    1609 Not Provided         CAT A      720     5401000
#4 4           4      8301       11188         12289   1451    1748      Covered         CAT B      620     5373000
#5 5           5     10510       12629         13921   1770    2111 Not Provided         CAT B      450     4662000
#6 6           6      6665        5142          9972   1442    1733         Open         CAT B      760     4526000

更新

如果我们需要获取异常值,在map 步骤中,我们从boxplot.stats 中提取outlier

outliers <- function(dataframe){
dataframe %>%
     select_if(is.numeric) %>% 
      map(~ boxplot.stats(.x)$out) 
  

  }
outliers(Clean_Data)

或者用NA 替换异常值(这也将保留行位置)

outlierreplacement <- function(dataframe){
   dataframe %>%          
           map_if(is.numeric, ~ replace(.x, .x %in% boxplot.stats(.x)$out, NA)) %>%
           bind_cols 
         

  
}
outlierreplacement(Clean_Data)

【讨论】:

  • 感谢您的回答。我们也可以输出不同向量中的所有异常值吗?
  • @Neil 我们可以将其输出为vectors 的list。更新了帖子
  • @Neil BTW,当您说删除异常值时,是删除该观察值还是将其更改为 NA?
  • 我可以用complete.cases 删除它。一个问题map 函数是做什么的?
  • 非常感谢您的回答和解释。不胜感激!
【解决方案2】:

这是我在 Heart Disease UCI 数据上所做的事情

df <- as.data.frame(read.csv("heart.csv"))
boxplot(df)
findOutliers <- function(dataframe){
  dataframe %>%Heart Disease UCI
    select_if(is.numeric) %>% 
    map(~ boxplot.stats(.x)$out)
}
outliers <- findOutliers(df)
temp <- list()
for (col in names(outliers)) {
  outlier <- outliers[[col]]
  if (length(outlier) > 0) {
    temp[col] <- df[-which(df[[col]] %in% outlier),][col]
  } else {
    temp[col] <- df[col]
  }
}
boxplot(temp)

在去除异常值之前

去除异常值后

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-08
    • 2013-04-11
    • 2017-10-01
    • 2021-02-08
    • 2018-02-21
    • 2013-10-09
    • 1970-01-01
    • 2021-11-13
    相关资源
    最近更新 更多