Использование повторяющегося цикла для поиска нескольких выбросов?

#r #outliers

#r #выбросы

Вопрос:

Я довольно новичок в R и борюсь либо с циклом повторения, либо с поиском выбросов, либо с обоими.

У меня большой, но ненадежный набор данных в виде матрицы. Я использую выбросы пакета для поиска выбросов в наборе данных, в частности, в каждой строке моей матрицы данных, однако для каждой строки есть несколько выбросов. Для поиска более одного выброса я попытался использовать цикл повторения для замены выбросов (средним значением строки) до тех пор, пока стандартное отклонение строки не окажется ниже определенного заданного значения.

 replaceoutliers <- function(data, standarddeviationthreshold) {
for(k in 1:nrow(data)) {
    repeat{
        data[k,] <- rm.outlier(data[k,], fill=TRUE, median=FALSE, opposite=FALSE)
            if(sd(data[k,]) > standarddeviationthreshold) {
            break
          }
        }
    }
    View(data)
}
 

Функция выполняется, но заменяет только высокое значение в каждой строке. Есть ли проблема в цикле повторения? Кто-нибудь знает о пакете, который найдет и заменит несколько выбросов? До сих пор я не смог оштрафовать ни одного.

Спасибо!

Редактировать: я не могу поделиться данными, которые я использую, но это тест, который я провел: я передал функцию

 data <- matrix(c(1:16)^2, nrow=4, ncol=4)
data
         [,1] [,2] [,3] [,4]
[1,]    1   25   81  169
[2,]    4   36  100  196
[3,]    9   49  121  225
[4,]   16   64  144  256

replaceoutliers(data, 1)
     [,1] [,2] [,3]     [,4]
[1,]    1   25   81 35.66667
[2,]    4   36  100 46.66667
[3,]    9   49  121 59.66667
[4,]   16   64  144 74.66667
 

Итак, мы видим, что высокие значения заменяются средним значением. Однако, например, в первой строке 1 также следует заменить.

Комментарии:

1. Нормальные данные. Забыл изменить его, извините.

2. По-видимому, rm.outlier(..., fill=TRUE) является идемпотентным.

3. Итак, если я изменю то, что я использую для идентификации выбросов, я должен быть готов?

Ответ №1:

Вам лучше использовать outlier функцию напрямую, чтобы последовательно удалять выбросы:

 replaceoutliers <- function(x, threshold) {
  t(apply(data, 1, function(row) {
    exclude <- rep(FALSE, length(row))
    repeat {
      outliers <- outlier(row[!exclude], logical=TRUE)
      exclude[!exclude] <- outliers
      if (sd(row[!exclude]) < threshold) break
    }
    row[exclude] <- mean(row)
    row
  }))
}
 

Здесь выбросы последовательно удаляются из данных и заменяются средним значением, пока не будет нарушено желаемое стандартное отклонение.

Некоторые примечания:

У вас неправильное направление для теста стандартного отклонения. Стандартное отклонение будет уменьшаться по мере замены выбросов средним значением.

outlier находит один выброс в данных, худшее значение. Сохранение логического для удаленных значений позволяет выполнять последовательное удаление при отслеживании позиций данных.

Нет гарантии, что меньшее значение будет удалено на второй итерации. Для первой строки вы удалите 81 перед 1 удалением .

Если вы попытаетесь получить слишком низкое стандартное отклонение, тест завершится неудачно. Для этого можно было бы закодировать защиту, но я этого не сделал:

 > replaceoutliers(data, 50)
     [,1] [,2] [,3] [,4]
[1,]    1   25   81   69
[2,]    4   36  100   84
[3,]    9   49  101  101
[4,]   16   64  120  120
> replaceoutliers(data, 34)
     [,1] [,2] [,3] [,4]
[1,]    1   25   69   69
[2,]    4   36   84   84
[3,]    9   49  101  101
[4,]   16   64  120  120
> replaceoutliers(data, 33)
 Error in if (sd(row[!exclude]) < threshold) break : 
  missing value where TRUE/FALSE needed