Проблема при передаче переменной со знаком доллара ($) в aes() в сочетании с facet_grid() или facet_wrap()

#r #ggplot2 #density-plot #facet-grid #dollar-sign

#r #ggplot2 #r-faq

Вопрос:

В данный момент я провожу некоторый анализ в ggplot2 для проекта, и случайно я наткнулся на какое-то (для меня) странное поведение, которое я не могу объяснить. Когда я пишу aes(x = cyl, ...) , график выглядит иначе, чем при передаче той же переменной с использованием aes(x = mtcars$cyl, ...) . Когда я удаляю facet_grid(am ~ .) оба графика, они снова становятся одинаковыми. Приведенный ниже код смоделирован после кода в моем проекте, который генерирует такое же поведение:

 library(dplyr)
library(ggplot2)

data = mtcars

test.data = data %>%
  select(-hp)

ggplot(test.data, aes(x = test.data$cyl, y = mpg))  
  geom_point()   
  facet_grid(am ~ .)  
  labs(title="graph 1 - dollar sign notation")

ggplot(test.data, aes(x = cyl, y = mpg))  
  geom_point()  
  facet_grid(am ~ .)  
  labs(title="graph 2 - no dollar sign notation")
  

Вот изображение графика 1:

график 1 - обозначение со знаком доллара

Вот изображение графика 2:

график 2 - нет обозначения со знаком доллара

Я обнаружил, что могу обойти эту проблему, используя aes_string вместо aes и передавая имена переменных в виде строк, но я хотел бы понять, почему ggplot ведет себя таким образом. Проблема также возникает при аналогичных попытках с facet_wrap .

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

1. короткий ответ: никогда не используйте $ в aes()

2. ^_^ после шока, который я испытал сегодня, когда мой график внезапно стал выглядеть странно, я больше не буду этого делать. Тем не менее, я хотел бы понять, что происходит, потому что я никогда раньше не сталкивался с этой проблемой / поведением.

3. когда ggplot строит график, if разбивает наборы данных для каждого слоя на группы, определяемые эстетикой и фасетированием. Чтобы эта группировка была надежной, вам нужно, чтобы переменные происходили из одного data.frame , иначе ggplot может в конечном итоге использовать другой порядок для коэффициента фасетирования и остальной части отображения.

4. хм, но разве переменная не находится в том же data.frame в этом примере, независимо от того, пишу ли я aes(x = cyl, …) или aes(x = test.data $ cyl, …)? тест. данные — это data.frame, который я передаю в ggplot, и он содержит все переменные. Где я ошибаюсь? Большое спасибо за ваш быстрый ответ!

5. Дело в том, что, поскольку ggplot использует нестандартные методы оценки, а среда R и системы определения области видимости могут быть сложными, при использовании $ here вы предоставляете потенциально запутанную информацию, которая заставит ggplot реагировать непредсказуемо. Способы, при которых что-то может пойти не так, разнообразны, сложны и обычно неинтуитивны.

Ответ №1:

tl; dr

Никогда не используйте [ или $ внутри aes() .


Рассмотрим этот иллюстративный пример, в котором переменная f фасетирования намеренно находится в неочевидном порядке относительно x

 d <- data.frame(x=1:10, f=rev(letters[gl(2,5)]))
  

Теперь сравните, что происходит с этими двумя графиками,

 p1 <- ggplot(d)  
  facet_grid(.~f, labeller = label_both)  
  geom_text(aes(x, y=0, label=x, colour=f))  
  ggtitle("good mapping") 

p2 <- ggplot(d)  
  facet_grid(.~f, labeller = label_both)  
  geom_text(aes(d$x, y=0, label=x, colour=f))  
  ggtitle("$ corruption") 
  

введите описание изображения здесь

Мы можем получить лучшее представление о том, что происходит, посмотрев на data.frame, созданный внутри ggplot2 для каждой панели,

  ggplot_build(p1)[["data"]][[1]][,c("x","PANEL")]

    x PANEL
1   6     1
2   7     1
3   8     1
4   9     1
5  10     1
6   1     2
7   2     2
8   3     2
9   4     2
10  5     2

 ggplot_build(p2)[["data"]][[1]][,c("x", "PANEL")]

    x PANEL
1   1     1
2   2     1
3   3     1
4   4     1
5   5     1
6   6     2
7   7     2
8   8     2
9   9     2
10 10     2
  

Второй график имеет неправильное отображение, потому что, когда ggplot создает data.frame для каждой панели, он выбирает значения x в «неправильном» порядке.

Это происходит потому, что использование $ разрывает связь между различными отображаемыми переменными (ggplot должен предполагать, что это независимая переменная, которая, насколько ему известно, может поступать из произвольного, отключенного источника). Поскольку data.frame в этом примере не упорядочен в соответствии с фактором f , подмножество data.frames, используемое внутри для каждой панели, принимает неправильный порядок.

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

1. Большое спасибо за вашу помощь! Ваш пример потрясающий!

2. Эта проблема была исправлена в ggplot2 v3.0.0.9000