Ниже приведен пример использования набора данных 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.
Если вы хотите увидеть выбросы для каждого столбца 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")
Мне удалось добиться желаемого результата. Используя формулу для выбросов коробчатой диаграммы, я смог создать две аккуратные функции, которые не только служат желаемой цели, но и работают в рамках семантики 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
:
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]
}