Как обнаружить и заменить выброс из нескольких столбцов в одном наборе данных с помощью R? - PullRequest
0 голосов
/ 27 марта 2020

Я пытаюсь найти и заменить выбросы из нескольких числовых c столбцов. По моему скромному мнению, это не лучшая практика, но я пытаюсь разобраться в конкретных случаях использования. Отличный пример создания дополнительного столбца, который помечает строку как выброс, можно найти здесь , но он основан на одном столбце.

Мои данные выглядят следующим образом (для простоты я исключил столбцы с коэффициентами):

   Row ID   Value1 Value2
      1        6      1
      2        2     200
      3      100      3
      4        1      4
      5      250      5
      6        2      6
      7        8     300
      8      600     300
      9        2      9

Я использовал функцию для замены выбросов на NA во всех цифрах c столбцов:

replaceOuts = function(df) {
    map_if(df, is.numeric, 
           ~ replace(.x, .x %in% boxplot.stats(.x)$out, NA)) %>% 
    bind_cols 
}
test = replaceOuts(df)

Мой вопрос: как я могу заменить выбросы другим значением (например, среднее значение, медиана, ограниченное значение и т. Д. c.)? Любая помощь будет оценена!

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Вместо NA вы можете заменить значение на mean или median, что вы предпочитаете.

library(dplyr)
library(purrr)

replaceOuts = function(df) {
   map_if(df, is.numeric, 
          ~ replace(.x, .x %in% boxplot.stats(.x)$out, mean(.x))) %>%
   bind_cols 
}

replaceOuts(df)

# RowID Value1 Value2
#  <dbl>  <dbl>  <dbl>
#1     1     6       1
#2     2     2     200
#3     3   100       3
#4     4     1       4
#5     5   108.      5
#6     6     2       6
#7     7     8     300
#8     8   108.    300
#9     9     2       9

Замените mean на median любой другой функцией, которую вы хотите.

PS - Я думаю, что здесь лучше использовать mutate_if вместо map_if, поскольку в конце он избегает bind_cols.

df %>% mutate_if(is.numeric, ~replace(., . %in% boxplot.stats(.)$out, mean(.)))
0 голосов
/ 27 марта 2020

Я думаю, вам нужны пороговые значения minVal и maxMax. А затем замените значения вне диапазона (minVal, maxVal) на любое значение в myValue (среднее значение, медиана или то, что вам нужно)

# Could be any value for limits, i.e. 
minVal <- boxplot.stats(data$columnX)$stats[1]
maxVal <- boxplot.stats(data$columnX)$stats[5]
myValue <- median(data$columnX)

data[data$columnX < minVal | data$columnX > maxVal, "columnX"] <- myValue   

...