Игнорировать выбросы в ggplot2 boxplot

#r #ggplot2

#r #ggplot2

Вопрос:

Как бы мне игнорировать выбросы в ggplot2 boxplot? Я не просто хочу, чтобы они исчезли (т. Е. outlier.size = 0), но я хочу, чтобы они игнорировались таким образом, чтобы ось y масштабировалась для отображения 1-3-го процентиля. Мои выбросы приводят к тому, что «box» сжимается настолько, что он становится практически линией. Существуют ли какие-либо методы для решения этой проблемы?

Редактировать Вот пример:

 y = c(.01, .02, .03, .04, .05, .06, .07, .08, .09, .5, -.6)
qplot(1, y, geom="boxplot")
  

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

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

1. Некоторые примеры данных и воспроизводимый пример облегчат оказание вам помощи.

2. мой файл размером 200 мегабайт! Просто возьмите любой набор данных, в котором есть много точек данных между 1-м и 3-м квантилями и несколько выбросов (вам нужен только 1). Если выброс находится далеко от 1-го / 3-го, то обязательно блоки будут сжиматься, чтобы вместить выброс

3. Да, это то, что я имел в виду. Создайте такой набор данных и используйте dput (), чтобы опубликовать его здесь вместе с инструкцией ggplot(), которую вы используете. Помогите нам помочь вам.

4. Разве вы не можете просто изменить ограничения по оси y, чтобы «увеличить» интересующую вас часть оси y?

5. дайте мне посмотреть…. О да, извините. Просто сделайте fivenum() с данными, чтобы извлечь то, что IIRC используется для верхнего и нижнего шарниров на boxplots, и используйте этот вывод в scale_y_continuous() вызове, который показал @Ritchie. Это можно очень легко автоматизировать с помощью инструментов, предоставляемых R и ggplot. Если вам нужно также включить усы, рассмотрите возможность использования boxplot.stats() для получения верхнего и нижнего пределов усов и использования затем в scale_y_continuous() .

Ответ №1:

Используйте geom_boxplot(outlier.shape = NA) , чтобы не отображать выбросы и scale_y_continuous(limits = c(lower, upper)) изменять пределы оси.

Пример.

 n <- 1e4L
dfr <- data.frame(
  y = exp(rlnorm(n)),  #really right-skewed variable
  f = gl(2, n / 2)
)

p <- ggplot(dfr, aes(f, y))   
  geom_boxplot()
p   # big outlier causes quartiles to look too slim

p2 <- ggplot(dfr, aes(f, y))   
  geom_boxplot(outlier.shape = NA)  
  scale_y_continuous(limits = quantile(dfr$y, c(0.1, 0.9)))
p2  # no outliers plotted, range shifted
  

На самом деле, как показал Рамнатх в своем ответе (и Андри тоже в комментариях), имеет смысл обрезать шкалы после вычисления статистики через coord_cartesian .

 coord_cartesian(ylim = quantile(dfr$y, c(0.1, 0.9)))
  

(Вероятно, вам все равно придется использовать scale_y_continuous для исправления разрывов оси.)

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

1. Итак, мне пришлось бы вычислить нижний / верхний — возможно, путем вычисления 1-3-го процентиля? То есть нет автоматического способа сообщить gg-plot2 игнорировать выбросы и разумно масштабироваться?

2. Будьте осторожны с scale_y_continuous(ограничения = …) Это удалит данные, которые выходят за пределы, а затем выполнит статистические вычисления. Другими словами, это повлияет на среднее значение и другие обобщения. Если это то, чего вы хотите, тогда отлично. Альтернативой является использование coord_cartesian(limits = …) — это «увеличивает масштаб», не удаляя данные и не влияя на сводки.

3. @Andrie — спасибо! Я не хочу, чтобы это влияло на среднее значение и другие сводки.

4. coord_cartesian() по моему опыту, не очень хорошо работает с coord_flip() , поэтому я предпочитаю scale_y_continuous() .

5. Это лучшее решение. Причина, по которой я хочу скрыть выбросы, заключается в том, что я также наношу точки с дрожанием с помощью geom_jitter. В этом случае выбросы просто мешают и создают впечатление, что точек больше, чем должно быть.

Ответ №2:

Вот решение с использованием boxplot.stats

 # create a dummy data frame with outliers
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y))   geom_boxplot(aes(x = factor(1)))


# compute lower and upper whiskers
ylim1 = boxplot.stats(df$y)$stats[c(1, 5)]

# scale y limits based on ylim1
p1 = p0   coord_cartesian(ylim = ylim1*1.05)
  

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

1. 1 для автоматического вычисления, 1 для использования coord_cartesian для увеличения, а не исключения данных

2. @Ben — у тебя две учетные записи? =) @Ramnath — это действительно элегантное решение

3. При использовании вышеуказанного метода ограничения могут быть смещены из-за небольшого экстремума с одной стороны и большого экстремума с другой, например, ylim <- c(-0.1, 1000) * 1.05 дает [1] 0.105 1050 . Чтобы получить равные ограничения вокруг среднего значения, которое вы могли бы использовать ylim c(-0.05, 0.05) * diff(ylim) / 2 . На мой взгляд, красивее.

4. @Ramnath что делает $ stats[c(1,5)]?

5. Это не работает, если вы используете facet_grid() . Тогда у вас будет несколько коробочных графиков вместо одного. Таким образом, вы не получаете правильных ограничений.

Ответ №3:

У меня была та же проблема, и я предварительно вычислил значения для Q1, Q2, медианы, ymin, ymax, используя boxplot.stats :

 # Load package and generate data
library(ggplot2)
data <- rnorm(100)

# Compute boxplot statistics
stats <- boxplot.stats(data)$stats
df <- data.frame(x="label1", ymin=stats[1], lower=stats[2], middle=stats[3], 
                 upper=stats[4], ymax=stats[5])

# Create plot
p <- ggplot(df, aes(x=x, lower=lower, upper=upper, middle=middle, ymin=ymin, 
                    ymax=ymax))   
    geom_boxplot(stat="identity")
p
  

Результатом является boxplot без выбросов.
введите описание изображения здесь

Ответ №4:

Одной из идей было бы упорядочить данные в двухпроходной процедуре:

  1. выполните первый проход, узнайте, каковы границы, например, сокращение при заданном процентиле, или стандартное отклонение N выше среднего, или …

  2. во втором проходе установите значения за пределами заданной границы на значение этой границы

Я должен подчеркнуть, что это старомодный метод, в котором должны доминировать более современные надежные методы, но вы все еще часто сталкиваетесь с этим.

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

1. Тот, кто только что молча проголосовал против: оставьте комментарий, чтобы объяснить, почему .

2. Это был не я. Просто хотел добавить, что наличие усов, которые заканчиваются процентилями (обычно 10-м и 90-м), кажется, очень распространенным явлением для данных об окружающей среде.

3. Я был молчаливым 1 , и хотел бы я предложить что-то другое. Упорядочивание почти всегда выполняется в econ finance. Если в SFun есть выбросы, которые портят визуализацию данных, интересно, как они влияют на анализ данных.

4. перечитывая этот пост, вы упомянули, что упорядочивание окон является более старой техникой…. какие могут быть более современные методы?

5. В целом, надежные методы являются развитием последних 30 с лишним лет.

Ответ №5:

gg.layers::geom_boxplot2 это именно то, что вы хотите.

 # remotes::install_github('rpkgs/gg.layers')
library(gg.layers)
library(ggplot2)
p <- ggplot(mpg, aes(class, hwy))
p   geom_boxplot2(width = 0.8, width.errorbar = 0.5)
  

https://rpkgs.github.io/gg.layers/reference/geom_boxplot2.html
введите описание изображения здесь

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

1. Спасибо!! Протестировано с моими данными, работает идеально! Я бы рекомендовал это решение, хотя я не уверен в стабильности / долговременной поддержке github things.

2. Привет @Gildas, это пакет с долгосрочной поддержкой, который я использую каждый день, github.com/rpkgs/Ipaper .

3. Чем это отличается от geom_boxplot() других вариантов изменения ширины рамки и / или усов?

4. Это параметр width и width.errorbar элемент управления. Вы можете найти примеры в rpkgs.github.io/gg.layers/reference/geom_boxplot2.html .

5. Я не вижу на этой странице никаких объяснений различий между ними.

Ответ №6:

Если вы хотите принудительно расширить усы до максимального и минимального значений, вы можете настроить coef аргумент. Значение по умолчанию для coef равно 1.5 (т.е. длина усов по умолчанию в 1,5 раза больше IQR).

 # Load package and create a dummy data frame with outliers 
#(using example from Ramnath's answer above)
library(ggplot2)
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y))   geom_boxplot(aes(x = factor(1)))

# create boxplot where whiskers extend to max and min values
p1 = ggplot(df, aes(y = y))   geom_boxplot(aes(x = factor(1)), coef = 500)
  

изображение p0

изображение p1

Ответ №7:

Просто, грязно и эффективно. geom_boxplot (выброс.альфа = 0)

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

1. Привет, это не решает проблему слишком большого расширения шкалы y. В OP сказано: «Я не просто хочу, чтобы они исчезли (т. Е. outlier.size = 0), но я хочу, чтобы они игнорировались, чтобы ось y масштабировалась для отображения 1-3-го процентиля».

Ответ №8:

Опция «coef» функции geom_boxplot позволяет изменять пороговое значение выбросов в терминах межквартильных диапазонов. Этот параметр задокументирован для функции stat_boxplot. Чтобы отключить выбросы (другими словами, они обрабатываются как обычные данные), можно вместо значения по умолчанию 1.5 указать очень высокое значение ограничения:

 library(ggplot2)
# generate data with outliers:
df = data.frame(x=1, y = c(-10, rnorm(100), 10)) 
# generate plot with increased cutoff for outliers:
ggplot(df, aes(x, y))   geom_boxplot(coef=1e30)
  

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

1. Это просто расширяет границы, это вообще не изменяет масштаб диаграммы