Могу ли я предложить несколько иной подход.
Преобразуйте ваши данные из широкой в длинную форму, а затем рассчитайте выбросы, используя квантили и интеркантильные диапазоны.
Затем отфильтруйте выбросы и выполните обратное преобразование.в широкой форме.Удаление строк с выбросами оставляет желаемый результат
Опираясь на @Steen Harsted
library(tidyverse)
set.seed(1)
outlier_H_rem <- tibble(
var1 = rnorm(10, 0, 1),
var2 = rnorm(10, 0, 1),
var3 = rnorm(10, 0, 1)) %>%
#Introduce outliers
rbind(c(5, 0, 0), c(0,7, 0))
outlier_H_rem
# A tibble: 12 x 3
var1 var2 var3
<dbl> <dbl> <dbl>
1 -0.626 1.51 0.919
2 0.184 0.390 0.782
3 -0.836 -0.621 0.0746
4 1.60 -2.21 -1.99
5 0.330 1.12 0.620
6 -0.820 -0.0449 -0.0561
7 0.487 -0.0162 -0.156
8 0.738 0.944 -1.47
9 0.576 0.821 -0.478
10 -0.305 0.594 0.418
11 5 0 0
12 0 7 0
outlier_H_rem %>%
# Collect dat in tidy form
tidyr::gather("Feature", "Value", everything()) %>%
ggplot2::ggplot(aes(x=Feature, y=Value)) +geom_boxplot()
Теперь вот как определитьвыбросы с использованием инструментов из тидиверса
outlier_H_rem %>%
# Collect data in tidy form
tidyr::gather("Feature", "Value", everything()) %>%
# Group by "Feature" and calculate outliers using iqr and quantiles
# Also adding a row counter
group_by(Feature) %>%
mutate(r=1:n()) %>%
mutate(q1 = quantile(Value,probs=0.25),
q3 = quantile(Value,probs=0.75),
iqr = IQR(Value),
outlier = if_else((q1-1.5*iqr)>Value | (q3+1.5*iqr)<Value, TRUE, FALSE)) %>%
# Filter out the ouliers
filter(!outlier) %>%
# deselect calculated rows
select(-q1, -q3, -iqr, -outlier) %>%
# Spread the results again.
# optionally remove rows with rows with NA (contained outliers) using na.omit()
spread(Feature, Value) %>%
# remove row counter
select(-r)
# A tibble: 12 x 3
var1 var2 var3
* <dbl> <dbl> <dbl>
1 -0.626 1.51 0.919
2 0.184 0.390 0.782
3 -0.836 -0.621 0.0746
4 1.60 NA NA
5 0.330 1.12 0.620
6 -0.820 -0.0449 -0.0561
7 0.487 -0.0162 -0.156
8 0.738 0.944 NA
9 0.576 0.821 -0.478
10 -0.305 0.594 0.418
11 NA 0 0
12 0 NA 0