Как мне легко найти выбросы на коробчатой ​​диаграмме

Ниже приведен пример использования набора данных mtcars. Есть один выброс со значением 33,9, но мне нужна функция, которая находит их все для данного столбца.

library(dplyr)
library(ggplot2)

mtcars %>%
  ggplot(aes(x = "", y = mpg)) +
  geom_boxplot(fill = "#2645df")

Я не знаю формулы для определения пределов усов коробчатой ​​диаграммы, поэтому я использовал приведенный выше график, чтобы найти это значение, а затем изменил его вручную:

res = ifelse(mtcars$mpg > 33, "outlier", "not outlier")
res = ifelse(mtcars$mpg < 10, "outlier", "not outlier")

Этот подход одновременно неэффективен и неверен: 33 не являются нижним пределом для выбросов, как и 10.

@LTyrone спасибо за помощь в публикации этого вопроса. Я ответил сам, указав код, который намеревался найти в прошлом году. Я все еще привыкаю к ​​SO и думаю, что понимаю редактирование, хотя считаю, что новое, более простое описание вопроса позволяет избежать первоначальной проблемы, которую я пытался решить... Если бы я мог получить отзыв о том, как я мог бы лучше объяснить вопрос, учитывая ответ, который я ожидал (тот, который я опубликовал), он будет очень много значить для меня. Заранее спасибо!

Pikada 04.09.2024 03:08

Огромное спасибо за вашу помощь и понимание!

Pikada 04.09.2024 18:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
56
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Если вы хотите увидеть выбросы для каждого столбца mtcars, вы можете нормализовать их значения (без этого вы ничего не увидите), а затем Pivot_wider и построить график с выбросами = TRUE.

mtcars %>%
  mutate(across(everything(), scale)) %>%
  pivot_longer(cols = everything()) %>%
  ggplot(aes(x = name, y = value)) +
  geom_boxplot(
    outliers = TRUE,
    fill = "#2645df")  

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

Pikada 04.09.2024 03:15

Мне удалось добиться желаемого результата. Используя формулу для выбросов коробчатой ​​диаграммы, я смог создать две аккуратные функции, которые не только служат желаемой цели, но и работают в рамках семантики tidyverse:

# smaller function to find the boxplot wisker limits:

outlierLimits = function(x, extreme = F){
  qts = quantile(x, c(.25, .75), names = F)
  
  IQR = qts[2] - qts[1]
  
  ret = c(
    
    lower = qts[1] - IQR*1.5,
    upper = qts[2] + IQR*1.5,
    lower.extreme = qts[1] - IQR*3,
    upper.extreme = qts[2] + IQR*3
    
  )[c(T, T, extreme, extreme)]
  
  return(ret)
}
# The function I was looking for:

outlierClassify = function(x, extreme = F,
                           labels = c("regular", "outlier",
                                      "extreme")[c(T,T,extreme)]){
  lims = outlierLimits( x, extreme )
  
  ret = ifelse(x > lims[1] & x < lims[2],
               labels[1], labels[2])
  
  if (extreme){
    ret[ ret != labels[1] ] = ifelse(
      
      x[ ret != labels[1] ] > lims[3] & 
        x[ ret != labels[1] ] < lims[4],
      
      labels[2], labels[3]
    )
  }
  return(ret)
}

Таким образом, функция outlierClassify возвращает вектор символов, который относится к входному вектору x.

Вот несколько замечательных примеров использования:

# simply obtaining the resulted vector

outlierClassify(mtcars$mpg, F)
# using it with mutate()
library(dplyr)

test = mtcars %>%
  select(mpg, cyl) %>%
  mutate(car = rownames(mtcars),
         .before = 1) %>% 

  # added an 'extreme' oulier for examplification
  rbind(data.frame(
    car = "UNO Mille", mpg = 34, cyl = 6
  )) %>% 
  group_by(cyl) %>% 
  mutate(outliers = outlierClassify(mpg, T),
         .after = mpg)
# using it with ggplot
library(ggplot2)

test %>% 
  ggplot(aes(x = as.factor(cyl), y = mpg))+
  geom_boxplot(outlier.shape = NA, fill = "#2645df", alpha = .6)+
  geom_jitter(aes(color = outliers), width = .1)+
  #making it pretty
  scale_color_manual(values = c("red", "darkorange", "black"))+
  theme_minimal()+
  theme(plot.background = element_rect(fill = "wheat3"))

Также смотрите ?boxplot.stats.

Axeman 04.09.2024 06:03

@Axeman Я изучил это, но нашел результат запутанным и не очень точным, поэтому в итоге я создал свою собственную вспомогательную функцию. Если бы вы могли использовать это в ответе, было бы неплохо узнать, как это можно реализовать...

Pikada 04.09.2024 18:46
Ответ принят как подходящий

Вы можете использовать boxplot.stats:

my_outliers <- function(x, coef = 1.5) boxplot.stats(x, coef = coef)$out

Это то, что graphics::boxplot использует. Это работает немного иначе, чем ggplot, что, я думаю, эквивалентно:

my_outliers2 <- function(x, coef = 1.5) {
  x[x > quantile(x, 0.75) + IQR(x) * coef | x < quantile(x, 0.25) - IQR(x) * coef]
}

Это отличная работа! Я по-прежнему предпочитаю свой подход, поскольку выполнение IQR вручную немного быстрее (альфа = 5%, n = 3000). Но мне очень понравилось, что вы показали разницу между графикой::boxplot и ggplot2::geom_boxplot.

Pikada 05.09.2024 02:09

Другие вопросы по теме