Winsorization 90% на нескольких переменных - PullRequest
0 голосов
/ 07 июня 2019

В моих реальных данных у меня есть несколько выбросов для нескольких переменных.Мои данные выглядят примерно так, как показано ниже, но числа абсолютно случайны.Я хотел бы вытащить все точки данных, которые больше или меньше 2 SD, используя винсоризацию.

df<-read.table(header=T, text="id, group, test1, test2
1, 0, 57, 82
2, 0, 77, 80
3, 0, 67, 90
4, 0, 15, 70
5, 0, 58, 72
6, 1, 18, 44
7, 1, 44, 44
8, 1, 18, 46
9, 1, 20, 44
10, 1, 14, 38")

До сих пор я определил свои выбросы для переменных test1 и test2 для каждой группы, используя следующуюкод:

outlier <- function(x, SD = 2){
  mu <- mean(x)
  sigma <- sd(x)
  out <- x < mu - SD*sigma | x > mu + SD*sigma
  out
}

# identify the outliers for each variable by each group
with(df, ave(test1, group, FUN = outlier))
with(df, ave(test2, group, FUN = outlier))

# add these new-found outliers to the data set
df$out1 <- with(df, ave(test1, group, FUN = outlier))
df$out2 <- with(df, ave(test2, group, FUN = outlier))

Мне известна функция winsorize в пакете robustHD, но я не уверен: 1).как адаптировать команду к 90% винсоризации (2 SD), 2).обеспечение винзоризации для 2 разных групп, 3).и включение нескольких переменных в эту winsorization.

Дополнительно, но не обязательно ... есть ли способ увидеть, что функция 'winsorize' изменила числа с тех, на которые числа были изменены?

Ответы [ 2 ]

1 голос
/ 08 июня 2019

Поясните сначала, как вы хотите улучшить ваши данные. У вас есть несколько вариантов.

  1. Используйте средние пределы +/- 2sd в качестве экстремальных значений и замените все внешние значения на эти
  2. Используйте наблюдаемое значение рядом со средним пределом +/- 2sd
  3. Используйте 90% квантиль

В вариантах 1 и 3 вы, возможно, будете вводить значения в свою worsorized переменную, которые не наблюдались, в варианте 2 вы будете иметь только наблюдаемые значения. Также обратите внимание, что квантиль (5%, 95%) не обязательно будет близок к 2 * sd, если у вас нет нормально распределенных данных с хорошим поведением.

Для процесса винсоризации вы можете использовать DescTools::Winsorize(), который принимает как пробники, так и значения для лимитов.

Реализация 1)

x <- rnorm(100)
w1 <- Winsorize(x, 
                minval = mean(x) - 2*sd(x), 
                maxval = mean(x) + 2*sd(x))

Для 2) вы можете использовать что-то вроде

w2 <- Winsorize(x, 
                minval = max(Coalesce(x[x <= mean(x)-2*sd(x)], mean(x)-2*sd(x))), 
                maxval = min(Coalesce(x[x >= mean(x)+2*sd(x)], mean(x)+2*sd(x))))

Укажите некоторые возрастающие значения для случаев, когда значения не выходят за пределы. Coalesce() возвращает первое непустое значение, поэтому Winsorize() всегда получит действительный предел.

Вариант 3) по умолчанию для функции

w3 <- Winsorize(x, probs=c(0.05, 0.95))

Определить функцию для группового применения как (здесь для варианта 1):

df$w1 <- unsplit(
           tapply(df$test1, df$group,
                  function(x) Winsorize(x, 
                                        minval = mean(x) - 2*sd(x), 
                                        maxval = mean(x) + 2*sd(x)) )
         , f=df$group)

Замененные значения можно найти с помощью

cbind(x, w1)[x!=w1,]
1 голос
/ 07 июня 2019

Вот начало - надеюсь, у кого-то есть лучшее решение для вас.

library(tidyverse)
df <- tibble::tribble(
  ~id, ~group, ~test1, ~test2,
  1,      0,     57,     82,
  2,      0,     77,     80,
  3,      0,     67,     90,
  4,      0,     15,     70,
  5,      0,     58,     72,
  6,      1,     18,     44,
  7,      1,     44,     44,
  8,      1,     18,     46,
  9,      1,     20,     44,
  10,      1,     14,     38
)
df
#> # A tibble: 10 x 4
#>       id group test1 test2
#>    <dbl> <dbl> <dbl> <dbl>
#>  1     1     0    57    82
#>  2     2     0    77    80
#>  3     3     0    67    90
#>  4     4     0    15    70
#>  5     5     0    58    72
#>  6     6     1    18    44
#>  7     7     1    44    44
#>  8     8     1    18    46
#>  9     9     1    20    44
#> 10    10     1    14    38

library(DescTools)
df %>%
  group_by(group) %>%
  mutate(
    test2_winsorized = DescTools::Winsorize(
      test2,
      maxval = quantile(df$test2, 0.90),
      minval = quantile(df$test2, 0.10)
    ),
    test1_winsorized = DescTools::Winsorize(
      test1,
      maxval = quantile(df$test1, 0.90),
      minval = quantile(df$test1, 0.10)
    )
  )
#> # A tibble: 10 x 6
#> # Groups:   group [2]
#>       id group test1 test2 test2_winsorized test1_winsorized
#>    <dbl> <dbl> <dbl> <dbl>            <dbl>            <dbl>
#>  1     1     0    57    82             82               57  
#>  2     2     0    77    80             80               68  
#>  3     3     0    67    90             82.8             67  
#>  4     4     0    15    70             70               15  
#>  5     5     0    58    72             72               58  
#>  6     6     1    18    44             44               18  
#>  7     7     1    44    44             44               44  
#>  8     8     1    18    46             46               18  
#>  9     9     1    20    44             44               20  
#> 10    10     1    14    38             43.4             14.9

Создано в 2019-06-06 пакетом представ. (v0.2.1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...