Почему stat_summary отображает несколько строк в зависимости от переменной? - PullRequest
3 голосов
/ 01 апреля 2020

Я задал этот вопрос немного go. В этом решение, кажется, работает иногда . Вот пример использования набора данных mpg.

Моя цель - поместить вертикальную линию, где медиана моих данных встречается для каждого аспекта, используя stat_summary. Обратите внимание, что когда я использую решение в связанном вопросе в столбце displ, решение работает так, как нужно. Но когда я использую его в столбце cty, рисуется несколько линий. Почему это так?

Показанный ниже пример моей проблемы.

library(tidyverse)

mpg %>% 
  ggplot(aes(x=displ, group=cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(xintercept=stat(x), y=0), fun = median, geom = 'vline')
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

mpg %>% 
  ggplot(aes(x=cty, group=cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(xintercept=stat(x), y=0), fun = median, geom = 'vline')
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Создано в 2020-04-01 пакетом Представить (v0.3.0)

Ответы [ 3 ]

4 голосов
/ 01 апреля 2020

Мы можем предварительно вычислить медиану, используя group_by и mutate, которые я часто нахожу более надежными и простыми для понимания в ее поведении, а затем просто использовать geom_vline. Не можете ответить со стороны stat_summary, но интересно узнать ответ.

mpg %>%
  group_by(cyl) %>%
  mutate(cty_med = median(cty)) %>%
  ggplot(aes(x=cty))+
  geom_histogram()+
  facet_grid(~cyl)+
  geom_vline(aes(xintercept=cty_med))

enter image description here

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

f <- function(df, fct, var) {
  df %>%
    group_by({{fct}}) %>%
    mutate(med = median({{var}})) %>%
    ggplot(aes(x={{var}}))+
    geom_histogram() +
    facet_grid(cols = vars({{fct}})) +
    geom_vline(aes(xintercept=med))
}

f(mpg, cyl, cty)
f(mpg, cyl, displ)
3 голосов
/ 01 апреля 2020

Деметрий, вот код R, который даст вам то, что вам нужно:

library(tidyverse) 

g <- mpg %>% 
     ggplot(aes(x=cty)) + 
     geom_histogram() + 
     stat_summary(aes(x = 0, xintercept = stat(y), y = cty), 
                     fun.y = median, geom = "vline", colour = "red") + 
     facet_grid(~ cyl)


g 

Функция stat_summary () настроена для вычисления сводки (в данном случае, медианы) для переменной указано в его аргументе у. Напротив, функция geom_histogram () создает гистограмму для переменной, указанной в ее аргументе x. Поэтому вы должны быть осторожны с указанием аргумента y для функции stat_summary (), как показано в приведенном выше коде.

Обратите внимание, что вам не нужно использовать group = cyl в вызове ggplot (), если вы используете facet_grid () или facet_wrap () для создания нескольких графических панелей. Группировка и фасетирование - это совершенно разные операции построения графиков: при группировании на разных панелях отображаются одинаковые ; фасетирование покажет разные группы данных на разных панелях.

Приложение 1

Чтобы убедиться, что сводная статистика была правильно рассчитана для каждой панели, пригодится следующая команда:

ggplot_build(g)$data

Прокрутите до конца вывода, созданного этой командой, чтобы найти значения xintercept, используемые R - это должны быть медианы, нанесенные на различные панели. В качестве альтернативы, извлеките эти значения непосредственно с помощью:

ggplot_build(g)$data[[2]]

Значения xintercept можно сравнить с независимо вычисленными медианными значениями cty для каждого уровня cyl для обеспечения согласования.

Приложение 2

Выбор по умолчанию для ширины бина для geom_histogram () требует некоторого внимания. Вы можете попробовать что-то вроде этого, чтобы разрешить выбор переменной пропускной способности для разных панелей:

theme_set(theme_bw())

g <- mpg %>% 
  ggplot(aes(x=cty)) + 
  geom_histogram(binwidth = function(x) 2 * IQR(x) / (length(x)^(1/3)), 
             fill = "lightblue3", colour = "white") + 
  stat_summary(aes(x = 0, xintercept = stat(y), y = cty), 
        fun.y = median, geom = "vline", colour = "red2") + 
  facet_wrap(~ cyl, scales = "free_x")


g 

Смотрите эту ссылку для других возможностей выбора пропускной способности: https://github.com/tidyverse/ggplot2/issues/2312.

2 голосов
/ 01 апреля 2020

Я сделал еще один пост, потому что я считаю, что мое исследование и решение достаточно отличаются от оригинала, чтобы оправдать его, но я могу объединиться, если кто-то не согласен. Итак, я считаю, что я выяснил причину проблемы с stat_summary и вашим текущим решением.

Я считаю, что stat_summary вычисляет свою сводную статистику c для каждого уникального значения x, когда переменная x принимает целочисленные значения.

library(tidyverse)

sapply(mpg, class)
#> manufacturer        model        displ         year          cyl        trans 
#>  "character"  "character"    "numeric"    "integer"    "integer"  "character" 
#>          drv          cty          hwy           fl        class 
#>  "character"    "integer"    "integer"  "character"  "character"

См. Ниже то же самое ранее при использовании hwy и cty, даже когда оба явно преобразуются в numeric вместо integer векторов.

mpg2 <- mpg %>%
  mutate(hwy = as.numeric(hwy),
         cty = as.numeric(cty))

sapply(mpg2, class)
#> manufacturer        model        displ         year          cyl        trans 
#>  "character"  "character"    "numeric"    "integer"    "integer"  "character" 
#>          drv          cty          hwy           fl        class 
#>  "character"    "numeric"    "numeric"  "character"  "character"

mpg2 %>%
  ggplot(aes(x=hwy, group=cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(xintercept=stat(x), y=0), fun = median, geom = 'vline')

enter image description here

И пример с cty:

mpg2 %>%
  ggplot(aes(x=cty, group=cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(xintercept=stat(x), y=0), fun = median, geom = 'vline')

enter image description here

Однако, если мы сделаем Небольшая корректировка до cty перед построением графика, добавление минутной десятичной точки, мы получаем желаемое поведение.

mpg %>%
  mutate(cty = cty + .000001) %>%
  ggplot(aes(x=cty, group=cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(xintercept=stat(x), y=0), fun = median, geom = 'vline')

enter image description here

И мы видим такое же поведение с hwy.

mpg %>%
  mutate(hwy = hwy + .000001) %>%
  ggplot(aes(x=hwy, group=cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(xintercept=stat(x), y=0), fun = median, geom = 'vline')

enter image description here Конечно, это не обязательно желаемое решение. Так как мы отображаем вертикальные линии, мы можем вместо этого создать новый aes, где вместо этого мы построим наш xintercept как функцию y и предоставим одну фиктивную переменную для x в пределах нашего диапазона данных. Это затем обманывает систему, заставляя строить только одну медиану от нашего единственного значения x, и дает нам желаемый график.

mpg %>%
  ggplot(aes(x=cty, group = cyl))+
  geom_histogram()+
  facet_grid(~cyl)+
  stat_summary(aes(x = 3, y = cty, xintercept = stat(y)), fun = median, geom = 'vline')

enter image description here

И там мы go! Совершенно запутанный, и не очень-то нравится в качестве решения, но я считаю, что вы должны go использовать stat_summary.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...