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

Я делаю некоторый анализ в ggplot2 на данный момент для проекта, и случайно я наткнулся на какое-то (для меня) странное поведение, которое я не могу объяснить. Когда я пишу aes(x = cyl,...) график выглядит по-другому, чем он делает, если я aes(x = mtcars$cyl,...) одну и ту же переменную с помощью aes(x = mtcars$cyl,...). Когда я facet_grid(am ~.) Оба графика снова 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:

graph 1 - dollar sign notation

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

graph 2 - no dollar sign notation

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

спасибо много за любую помощь заранее! Мне очень неудобно, если я не понимаю, что правильно...

Ответ 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, подмножество данных. Кадры, используемые внутри каждой панели, принимают неправильный порядок.