Ответ 1
Чтобы окрасить точки выброса так же, как и ваши ящики, вам нужно будет рассчитать выбросы и рассчитать их отдельно. Насколько мне известно, встроенная опция для раскраски выделяет все выбросы одного и того же цвета.
Пример файла справки
Используя те же данные, что и файл справки "geom_boxplot":
ggplot(mtcars, aes(x=factor(cyl), y=mpg, col=factor(cyl))) +
geom_boxplot()
Окраска точек выброса
Теперь может быть более оптимизированный способ сделать это, но я предпочитаю вычислять вещи вручную, поэтому мне не нужно гадать, что происходит под капотом. Используя пакет "plyr" , мы можем быстро получить верхний и нижний пределы использования метода по умолчанию (Tukey) для определения outlier, который является любой точкой вне диапазона [Q1 - 1.5 * IQR, Q3 + 1.5 * IQR]. Q1 и Q3 - кванты данных 1/4 и 3/4 данных, IQR = Q3 - Q1. Мы могли бы написать все это как один огромный оператор, но так как функция 'plyr' 'mutate' позволит нам ссылаться на недавно созданные столбцы, мы могли бы также разделить ее на более легкое чтение/отладку, например:
library(plyr)
plot_Data <- ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)
Мы используем функцию "ddply" , потому что мы вводим кадр данных и хотим, чтобы кадр данных был выводимым ( "d- > d" ply). Функция "mutate" в вышеупомянутом выражении "ddply" сохраняет исходный фрейм данных и добавляет дополнительные столбцы, а спецификация .(cyl)
сообщает вычислениям функций для каждой группировки значений "цил".
На этом этапе мы можем теперь построить квадрат, а затем перезаписать выбросы новыми цветными точками.
ggplot() +
geom_boxplot(data=plot_Data, aes(x=factor(cyl), y=mpg, col=factor(cyl))) +
geom_point(data=plot_Data[plot_Data$mpg > plot_Data$upper.limit | plot_Data$mpg < plot_Data$lower.limit,], aes(x=factor(cyl), y=mpg, col=factor(cyl)))
Что мы делаем в коде, это указать пустой слой ggplot, а затем добавить полевые диаграммы и геометрии точек с использованием независимых данных. Геометрия boxplot может использовать исходный фрейм данных, но я использую нашу новую "plot_Data", чтобы быть последовательной. Точечная геометрия тогда отображает только точки вылета, используя наши новые столбцы lower.limit и upper.limit для определения статуса outlier. Поскольку мы используем ту же спецификацию для эстетических аргументов "x" и "col", цвета волшебным образом сопоставляются между ящиками и соответствующими точками выброса.
Обновить. OP запросил более полное объяснение функции "ddply" , используемой в этом коде. Вот он:
Семейство функций "plyr" в основном является способом подмножества данных и выполнения функции для каждого подмножества данных. В этом частном случае мы имеем утверждение:
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)
Пусть это сломается в порядке, в котором будет написано утверждение. Во-первых, выбор функции "ddply" . Мы хотим рассчитать нижний и верхний пределы для каждого значения "цил" в данных "mtcars". Мы могли бы написать цикл "for" или другой оператор для вычисления этих значений, но потом нам пришлось бы написать еще один логический блок позже, чтобы оценить статус offlier. Вместо этого мы хотим использовать "ddply" для вычисления нижнего и верхнего пределов и добавления этих значений в каждую строку. Мы выбираем "ddply" (в отличие от "dlply", "d_ply" и т.д.), Потому что мы вводим кадр данных и хотим, чтобы кадр данных был выводимым. Это дает нам:
ddply(
Мы хотим выполнить оператор в кадре данных mtcars, поэтому добавим его.
ddply(mtcars,
Теперь мы хотим выполнить наши вычисления, используя значения "cyl" в качестве переменной группировки. Мы используем функцию "plyr" .()
для обозначения самой переменной, а не значения переменной, например:
ddply(mtcars, .(cyl),
Следующий аргумент определяет функцию, применяемую к каждой группе. Мы хотим, чтобы наш расчет добавлял новые строки в старые данные, поэтому мы выбираем функцию "mutate". Это сохраняет старые данные и добавляет новые вычисления в виде новых столбцов. Это контрастирует с другими функциями, такими как "суммирование", которое удаляет все старые столбцы, кроме переменных (-ов) группировки.
ddply(mtcars, .(cyl), mutate,
Последняя серия аргументов - это все новые столбцы данных, которые мы хотим создать. Мы определяем их, указав имя (без кавычек) и выражение. Во-первых, мы создаем столбец "Q1" .
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4),
Столбец "Q3" вычисляется аналогично.
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4),
К счастью, с помощью функции "mutate" мы можем использовать только что созданные столбцы как часть определения других столбцов. Это избавляет нас от необходимости писать одну гигантскую функцию или выполнять несколько функций. Нам нужно использовать "Q1" и "Q3" при вычислении межквартильного диапазона для переменной "IQR", и это легко с помощью функции "mutate".
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1,
Наконец-то мы хотим, чтобы мы были. Нам технически не нужны столбцы "Q1" , "Q3" и "IQR", но это делает наши нижние и верхние предельные уравнения намного легче читать и отлаживать. Мы можем написать наше выражение так же, как теоретическая формула: limits=+/- 1.5 * IQR
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)
Вырезая средние столбцы для удобочитаемости, это выглядит следующим образом:
plot_Data[, c(-3:-11)]
# mpg cyl Q1 Q3 IQR upper.limit lower.limit
# 1 22.8 4 22.80 30.40 7.60 41.800 11.400
# 2 24.4 4 22.80 30.40 7.60 41.800 11.400
# 3 22.8 4 22.80 30.40 7.60 41.800 11.400
# 4 32.4 4 22.80 30.40 7.60 41.800 11.400
# 5 30.4 4 22.80 30.40 7.60 41.800 11.400
# 6 33.9 4 22.80 30.40 7.60 41.800 11.400
# 7 21.5 4 22.80 30.40 7.60 41.800 11.400
# 8 27.3 4 22.80 30.40 7.60 41.800 11.400
# 9 26.0 4 22.80 30.40 7.60 41.800 11.400
# 10 30.4 4 22.80 30.40 7.60 41.800 11.400
# 11 21.4 4 22.80 30.40 7.60 41.800 11.400
# 12 21.0 6 18.65 21.00 2.35 24.525 15.125
# 13 21.0 6 18.65 21.00 2.35 24.525 15.125
# 14 21.4 6 18.65 21.00 2.35 24.525 15.125
# 15 18.1 6 18.65 21.00 2.35 24.525 15.125
# 16 19.2 6 18.65 21.00 2.35 24.525 15.125
# 17 17.8 6 18.65 21.00 2.35 24.525 15.125
# 18 19.7 6 18.65 21.00 2.35 24.525 15.125
# 19 18.7 8 14.40 16.25 1.85 19.025 11.625
# 20 14.3 8 14.40 16.25 1.85 19.025 11.625
# 21 16.4 8 14.40 16.25 1.85 19.025 11.625
# 22 17.3 8 14.40 16.25 1.85 19.025 11.625
# 23 15.2 8 14.40 16.25 1.85 19.025 11.625
# 24 10.4 8 14.40 16.25 1.85 19.025 11.625
# 25 10.4 8 14.40 16.25 1.85 19.025 11.625
# 26 14.7 8 14.40 16.25 1.85 19.025 11.625
# 27 15.5 8 14.40 16.25 1.85 19.025 11.625
# 28 15.2 8 14.40 16.25 1.85 19.025 11.625
# 29 13.3 8 14.40 16.25 1.85 19.025 11.625
# 30 19.2 8 14.40 16.25 1.85 19.025 11.625
# 31 15.8 8 14.40 16.25 1.85 19.025 11.625
# 32 15.0 8 14.40 16.25 1.85 19.025 11.625
Чтобы дать контрастность, если бы мы выполняли одно и то же выражение "ddply" с помощью функции "summary", вместо этого у нас были бы все одинаковые ответы, но без столбцов других данных.
ddply(mtcars, .(cyl), summarize, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)
# cyl Q1 Q3 IQR upper.limit lower.limit
# 1 4 22.80 30.40 7.60 41.800 11.400
# 2 6 18.65 21.00 2.35 24.525 15.125
# 3 8 14.40 16.25 1.85 19.025 11.625