Как концептуально работают функции ggplot stat_ *?

#r #ggplot2

#r #ggplot2

Вопрос:

В настоящее время я пытаюсь разобраться в различиях между stat_* и geom_* в ggplot2 . (Пожалуйста, обратите внимание, что это скорее вопрос, основанный на интересе / понимании, чем на конкретной проблеме, которую я пытаюсь решить).

Введение

Мое текущее понимание заключается в том, что stat_* функции применяют преобразование к вашим данным и что результат затем передается на geom_* для отображения.

Самым простым примером является преобразование идентификатора, которое просто передает ваши данные в нетрансформированном виде в geom.

 ggplot(data = iris)   
    stat_identity(aes(x = Sepal.Length, y = Sepal.Width) , geom= "point")
  

Более практичные варианты использования, по-видимому, заключаются в том, что вы хотите использовать некоторое преобразование и предоставить результаты в геометрию, отличную от геометрии по умолчанию, например, если вы хотите отобразить панель ошибок 1-го и 3-го квартилей, вы могли бы сделать что-то вроде:

 ggplot(data = iris)   
    stat_boxplot(aes(x=Species, y = Sepal.Length, ymax = ..upper.., ymin = ..lower..), geom = "errorbar")
  

Вопрос 1

Итак, как / когда эти преобразования применяются к набору данных и как именно данные проходят через них?

В качестве примера, скажем, я хотел провести stat_boxplot преобразование и построить точку 3-го квартиля, как бы я это сделал?

Моя интуиция была бы чем-то вроде :

 ggplot(data = iris)   
    stat_boxplot(aes(x=Species, y = ..upper..) , geom = "point")
  

или

 ggplot(data = iris)   
    stat_boxplot(aes(x=Species, y = Sepal.Length) , geom = "point")
  

однако обе ошибки с

 Error: geom_point requires the following missing aesthetics: y
  

Я предполагаю, что в рамках stat_boxplot преобразования он использует эстетику y и создает набор данных, не содержащий какой-либо y переменной, однако это приводит к ….

Вопрос 2

Где я могу узнать, какие переменные используются как часть stat_* преобразования и какие переменные они выводят? Возможно, я ищу не в тех местах, но документация мне совсем не кажется понятной…

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

1. Я не могу протестировать прямо сейчас, но я считаю, что вам нужно вызвать geom_point и передать stat_boxplot в его аргумент stat. Причина в том, что вам нужно передать x и y в aes geom_point, а ваш подход передает их в aes stat_boxplot.

2. Я не думаю, что это что-то изменит, извините, потому что оба stat_* и geom_* являются просто оболочками для layer() функции, но с фиксированными значениями аргументов stat и geom . Поэтому я думаю, что простое переключение на geom_point() все равно приведет к тому же вызову layer() . Тем не менее, спасибо за ваш комментарий!

3. Вы пробовали?

4. Я сделал — ggplot(data = iris) geom_point( aes(x=Species, y = Sepal.Length), stat = "boxplot") приводит к тому же сообщению об ошибке Error: geom_point requires the following missing aesthetics: y 🙁

Ответ №1:

Интересные вопросы…

В качестве справочной информации вы можете прочитать эту главу R for Data Science, посвященную грамматике графики. Я уверен, что книга Хэдли Уикхема о ggplot2 — еще лучший источник, но у меня его нет.

Основными шагами для построения графика с одним слоем и без фасета являются:

  1. Примените эстетическое отображение к входным данным (в простых случаях это выделение и переименование столбцов)
  2. Примените масштабное преобразование (если таковое имеется) к каждому столбцу данных
  3. Вычислите статистику для каждой группы данных (т. Е. для каждого вида в данном случае)
  4. Применить отображение эстетики к статистическим данным, обнаруженным с помощью ..<name>.. или stat(name)
  5. Применить корректировку положения
  6. Построение графических объектов
  7. Примените преобразования координат

Как вы догадались, поведение на шаге 3 аналогично dplyr::transmute() : оно использует все столбцы эстетики и выводит фрейм данных, содержащий в качестве столбцов все недавно вычисленные статистические данные и все столбцы, которые являются постоянными в группе. Вывод статистики также может иметь другое количество строк, чем на входе. Таким образом, действительно, в вашем примере y столбец не передается в геометрию.

Для этого мы хотели бы указать различные сопоставления на шаге 1 (перед stat) и на шаге 4 (перед geom). Я думал, что что-то подобное сработает:

 # This does not work:
ggplot(data = iris)   
  geom_point(
    aes(x=Species, y=stat(upper)), 
    stat=stat_boxplot(aes(x=Species, y=Sepal.Length)) )
  

… но это не так (stat должен быть строкой или объектом Stat, но stat_boxplot фактически возвращает объект слоя, как это делает geom_point).

ПРИМЕЧАНИЕ: stat(upper) является ли эквивалентная, более свежая, запись вашей ..upper..

Возможно, я ошибаюсь, но я не думаю, что есть способ сделать это непосредственно в ggplot. Что вы можете сделать, так это извлечь статистическую часть процесса выше и управлять ею самостоятельно, прежде чем вводить ggplot():

 library(tidyverse)
iris %>%
  group_by(Species) %>%
  select(y=Sepal.Length) %>% 
  do(StatBoxplot$compute_group(.)) %>%
  ggplot(aes(Species, upper))   geom_point()
  

Признаю, немного менее элегантно…

Что касается вашего вопроса 2, он находится в документе: см. Разделы Эстетика и вычисляемые переменные ?stat_boxplot

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

1. @gowerc, это тот ответ, который вы ожидали?