Как удалить выбросы из набора данных

У меня есть многомерные данные о красоте и возрастах. Возраст варьируется от 20 до 40 с интервалом 2 (20, 22, 24 .... 40), и для каждой записи данных им дается возраст и оценка красоты от 1 до 5. Когда я строю прямоугольные диаграммы этих данных (возраст по оси X, оценки красоты по оси Y), за пределами усов каждого прямоугольника появляются некоторые выбросы.

Я хочу удалить эти выбросы из самого фрейма данных, но я не уверен, как R вычисляет выбросы для своих ящичных диаграмм. Ниже приведен пример того, как могут выглядеть мои данные. введите описание изображения здесь


person Dan Q    schedule 24.01.2011    source источник
comment
Функция boxplot невидимо возвращает выбросы (среди другой статистики). Попробуйте foo <- boxplot(...); foo и прочтите ?boxplot, чтобы понять результат.   -  person Joshua Ulrich    schedule 25.01.2011
comment
Вы должны отредактировать свой вопрос в соответствии с комментарием, который вы дали на ответ @Prasad!   -  person aL3xa    schedule 25.01.2011
comment
@ aL3xa: это первое предложение второго абзаца.   -  person Joshua Ulrich    schedule 25.01.2011
comment
Релевантно: davidmlane.com/ben/outlier.gif   -  person eyjo    schedule 25.01.2011
comment
Можете ссылку на данные прислать?   -  person wordsforthewise    schedule 03.03.2017


Ответы (11)


Хорошо, вы должны применить что-то подобное к своему набору данных. Не заменяйте и не сохраняйте, иначе вы уничтожите свои данные! И, кстати, вы (почти) никогда не должны удалять выбросы из своих данных:

remove_outliers <- function(x, na.rm = TRUE, ...) {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)
  H <- 1.5 * IQR(x, na.rm = na.rm)
  y <- x
  y[x < (qnt[1] - H)] <- NA
  y[x > (qnt[2] + H)] <- NA
  y
}

Чтобы увидеть это в действии:

set.seed(1)
x <- rnorm(100)
x <- c(-10, x, 10)
y <- remove_outliers(x)
## png()
par(mfrow = c(1, 2))
boxplot(x)
boxplot(y)
## dev.off()

И еще раз: вы никогда не должны делать это в одиночку, выбросы просто должны быть такими! знак равно

РЕДАКТИРОВАТЬ: я добавил na.rm = TRUE по умолчанию.

РЕДАКТИРОВАТЬ2: Удалена функция quantile, добавлены индексы, поэтому функция стала быстрее! знак равно

введите описание изображения здесь

person aL3xa    schedule 24.01.2011
comment
Спасибо за помощь! Я бы подумал, что если R способен выводить выбросы в коробчатую диаграмму, мне не нужно делать эти промежуточные вычисления. Что касается удаления выбросов, это просто задание. - person Dan Q; 25.01.2011
comment
Хорошо, я кое-что упустил. Вы хотите удалить выбросы из данных, чтобы вы могли построить их с помощью boxplot. Это выполнимо, и тогда вы должны отметить ответ @Prasad, поскольку ответили на ваш вопрос. Если вы хотите исключить выбросы с помощью правила выброса q +/- (1.5 * H) и, следовательно, провести некоторый анализ, используйте эту функцию. Кстати, я сделал это с нуля, без поиска в Google, так что есть шанс, что я заново изобрел колесо с этой моей функцией ... - person aL3xa; 25.01.2011
comment
Вы не должны задавать вопросы о назначении в stackoverflow! - person hadley; 09.02.2011
comment
Значит ли это, что и на него не стоит отвечать? знак равно - person aL3xa; 09.02.2011
comment
Чтобы быть еще более общим, сделайте 1.5 аргументом функции по умолчанию. И разрешить отдельные нижний и верхний диапазоны: c(-1.5,+1.5) - person smci; 15.04.2015
comment
выбросы просто должны быть? Не обязательно. Они могут возникать из-за ошибок измерения и должны быть тщательно проверены. Когда выброс слишком велик, это может означать что-то или не очень. Вот почему (по крайней мере, в биологии) медиана обычно говорит больше о популяции, чем среднее значение. - person Rodrigo; 11.02.2017
comment
Отлично. Как насчет замены IQR на SD? например, H <- 8 * sd(x, na.rm = na.rm)? Будет ли это исключать значения выше или ниже среднего 8 SD? - person Rocky; 31.05.2017
comment
действительно, это было бы - person Moody_Mudskipper; 30.07.2018

Никто не опубликовал простейшего ответа:

x[!x %in% boxplot.stats(x)$out]

См. Также это: http://www.r-statistics.com/2011/01/how-to-label-all-the-outliers-in-a-boxplot/

person J. Win.    schedule 08.02.2011
comment
Действительно элегантно. Спасибо. Но нужно быть осторожным, если распределение имеет более одного режима, а выбросы действительно немногочисленны и разбросаны. - person KarthikS; 19.03.2015
comment
Было бы здорово, если бы вы смогли получить их индекс в наборе данных. То, как вы это сделаете, будет фильтровать на основе значения данных. Если коробчатая диаграмма также выполняет группировку, не обязательно одно и то же значение данных будет выпадать в каждой группе. - person adam; 12.06.2015
comment
Также важно отметить, что это не меняет набор данных. Это просто метод фильтрации. Поэтому, если вы собираетесь использовать набор данных без выбросов, присвойте его переменной. например result = x[!x %in% boxplot.stats(x)$out] - person Victor Augusto; 07.05.2017
comment
Наличие всего одной строчки кода не обязательно означает, что это просто! Не всегда легко разобраться в однострочном коде, особенно для новичков, и без комментариев. - person PM0087; 15.10.2019

Используйте outline = FALSE как вариант при построении блочной диаграммы (прочтите справку!).

> m <- c(rnorm(10),5,10)
> bp <- boxplot(m, outline = FALSE)

введите описание изображения здесь

person Prasad Chalasani    schedule 24.01.2011
comment
действительно, это удалит выбросы из самой диаграммы, но я хочу удалить выбросы из кадра данных. - person Dan Q; 25.01.2011
comment
Я вижу, тогда, как сказал @Joshua, вам нужно посмотреть данные, возвращаемые функцией boxplot (в частности, элементы out и group в списке). - person Prasad Chalasani; 25.01.2011

Функция boxplot возвращает значения, используемые для построения графика (что на самом деле затем выполняется с помощью bxp ():

bstats <- boxplot(count ~ spray, data = InsectSprays, col = "lightgray") 
#need to "waste" this plot
bstats$out <- NULL
bstats$group <- NULL
bxp(bstats)  # this will plot without any outlier points

Я намеренно не ответил на конкретный вопрос, потому что считаю статистической халатностью удаление «выбросов». Я считаю приемлемой практикой не наносить их на прямоугольную диаграмму, но удаление их только потому, что они превышают некоторое количество стандартных отклонений или некоторое количество межквартильных ширин, является систематическим и ненаучным искажением данных наблюдений.

person IRTFM    schedule 24.01.2011
comment
Что ж, уклоняться от вопроса, не зная, почему был задан вопрос, тоже не является хорошей практикой. Да, нецелесообразно удалять «выбросы» из данных, но иногда вам нужны данные без выбросов для конкретных задач. В задании по статистике, которое у меня было недавно, нам нужно было визуализировать набор без его выбросов, чтобы определить лучшую регрессионную модель для использования для данных. Так что! - person Alex Essilfie; 25.06.2012
comment
Я не считаю совет, который вы, возможно, получили в этой связи, по определению лучшей регрессионной модели, особенно убедительным. Вместо этого, если вам нужно было удалить выбросы для этой расплывчато сформулированной цели, то я думаю, что это плохо отразится на людях, которые это посоветовали, а не свидетельствует о недействительности моей позиции. - person IRTFM; 25.06.2012
comment
Я думаю, это законно, когда вы знаете, что удаляете шум. особенно в физиологических данных. - person roscoe1895; 29.03.2019
comment
да. Если у вас есть веские основания полагать, что отдельный процесс создает сигнал, это оправдание для удаления из данных. - person IRTFM; 29.03.2019

Я поискал пакеты, связанные с удалением выбросов, и нашел этот пакет (неожиданно названный «выбросами»!): https://cran.r-project.org/web/packages/outliers/outliers.pdf
если вы пройдете через него, вы увидите разные способы удаления выбросов, и среди них я нашел rm.outlier наиболее удобный для использования и, как сказано в приведенной выше ссылке: «Если выброс обнаружен и подтвержден статистическими тестами, эта функция может удалить его или заменить средним значением выборки или медианой», а также часть использования из тот же источник:
"Использование

rm.outlier(x, fill = FALSE, median = FALSE, opposite = FALSE)

Аргументы
x набор данных, чаще всего вектор. Если аргументом является фрейм данных, то sapply удаляет выброс из каждого столбца. Такое же поведение применяется с помощью apply, когда задана матрица.
fill Если установлено значение TRUE, вместо выброса помещается медиана или среднее значение. В противном случае выбросы просто удаляются.
median Если установлено значение TRUE, при замене выбросов вместо среднего используется среднее значение. напротив, если установлено значение ИСТИНА, дает противоположное значение (если наибольшее значение имеет максимальное отличие от среднего, оно дает наименьшее и наоборот) "

person Peyman    schedule 29.12.2016
comment
Это кажется отличным, но если у вас есть столбец временных рядов во фрейме данных, он меняет временные ряды. - person PM0087; 15.10.2019

x<-quantile(retentiondata$sum_dec_incr,c(0.01,0.99))
data_clean <- data[data$attribute >=x[1] & data$attribute<=x[2],]

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

person Gaurav Khare    schedule 23.10.2015

Не было бы:

z <- df[df$x > quantile(df$x, .25) - 1.5*IQR(df$x) & 
        df$x < quantile(df$x, .75) + 1.5*IQR(df$x), ] #rows

справиться с этой задачей довольно легко?

person d8aninja    schedule 28.07.2015

Добавив к предложению @sefarkas и используя квантиль в качестве отсечки, можно было бы изучить следующий вариант:

newdata <- subset(mydata,!(mydata$var > quantile(mydata$var, probs=c(.01, .99))[2] | mydata$var < quantile(mydata$var, probs=c(.01, .99))[1]) ) 

Это удалит точки за пределами 99-го квантиля. Следует проявлять осторожность, как то, что aL3Xa говорил о сохранении выбросов. Его следует удалять только для получения альтернативного консервативного взгляда на данные.

person KarthikS    schedule 19.03.2015
comment
Если у вас есть конкретная причина использовать 91-й процентиль вместо 99-го, вы можете его использовать. Это всего лишь эвристический - person KarthikS; 16.04.2017

1 способ сделать это

my.NEW.data.frame <- my.data.frame[-boxplot.stats(my.data.frame$my.column)$out, ]

or

my.high.value <- which(my.data.frame$age > 200 | my.data.frame$age < 0) 
my.NEW.data.frame <- my.data.frame[-my.high.value, ]
person Seyma Kalay    schedule 20.11.2019

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

Пики не всегда совпадают с выбросами, но часто они похожи.

Здесь показан пример: Этот набор данных считывается с датчика по последовательной связи. Случайные ошибки последовательной связи, ошибка датчика или и то, и другое приводят к повторяющимся, явно ошибочным точкам данных. В этом пункте нет статистической ценности. Возможно, это не выбросы, а ошибки. Детектор пика z-оценки смог сигнализировать о ложных точках данных и сгенерировал чистый результирующий набор данных: < img src = "https://i.stack.imgur.com/0oE2v.jpg" alt = "введите описание изображения здесь" />

person Marc Compere    schedule 01.08.2020

Попробуй это. Подайте свою переменную в функцию и сохраните o / p в переменной, которая будет содержать удаленные выбросы

outliers<-function(variable){
    iqr<-IQR(variable)
    q1<-as.numeric(quantile(variable,0.25))
    q3<-as.numeric(quantile(variable,0.75))
    mild_low<-q1-(1.5*iqr)
    mild_high<-q3+(1.5*iqr)
    new_variable<-variable[variable>mild_low & variable<mild_high]
    return(new_variable)
}
person Adipta Biwas    schedule 14.08.2019
comment
Пожалуйста, добавьте пояснение к своему ответу. См. Как ответить. - person ejderuby; 14.08.2019