Разница между backticks и кавычками в функции aes в ggplot

Хорошо, это немного странно. Я отвечал на вопрос для новичка вокруг geom_histogram, и OP опубликовал пример с использованием обратных ссылок. Он пренебрег тем, что добавил данные, поэтому решил, что нашел ответ, даже не заметив обратных шагов. Но другой (на самом деле более элегантный) ответ был отправлен без обратных ссылок. Это действительно не сработало, но с обратными шагами он работал намного лучше.

Но теперь я озадачен. Я не понимаю, почему должна была быть разница. Даже список ggplot почти идентичен, только элемент ggplot$mapping отличается, насколько я могу видеть (хорошо, это biggie). У меня есть googled, но я не вижу, что происходит.

Итак, вот код:

Этот (кавычки вокруг Log Number в aes):

#Generate some data
lon <- log(rnorm(1000, exp(6)))
state <- sample(c("c", "l", "t"), 1000, replace = T)
d <- data.frame(lon, state)
names(d) <- c("Log Number", "state")

# Plot it
gpsq <- ggplot(d, aes(x = 'Log Number', fill = state)) + geom_histogram()
print(gpsq)

дает этот:

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

Но этот (обратные ссылки вокруг Log Number в aes):

#Generate some data
lon <- log(rnorm(1000, exp(6)))
state <- sample(c("c", "l", "t"), 1000, replace = T)
d <- data.frame(lon, state)
names(d) <- c("Log Number", "state")

# Plot it
gpsq <- ggplot(d, aes(x = `Log Number`, fill = state)) + geom_histogram()
print(gpsq)

более корректно это дает:

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

Ответ 1

Обратные тики являются стандартным способом обозначения нестандартного имени переменной в R. Котировки используются для указания строки. Пример:

`bad name` = 1
`bad name`
# [1] 1

Это не работает с кавычками.

"bad name" = 1
"bad name"
# [1] "bad name"

Как правило, вы не должны использовать эти странные, нестандартные имена. Но, если вам когда-либо понадобится, это способ сделать это. Вы можете сделать что угодно,

`really-bad^name+violating*all()/[kinds] <- of == rules&!|` = 1
# works just fine

но это не значит, что вы должны.


Когда дело доходит до ggplot, если вы сделали

ggplot(mtcars, aes(x = wt, y = 1)) + geom_point()

вы ожидаете, что все значения y будут равны 1. И вы будете правы!

При цитируемой строке это одно и то же:

ggplot(mtcars, aes(x = wt, y = "mpg")) + geom_point()

кроме числа, как в приведенном выше случае y = 1, вы присвоили ему символ, который неявно преобразован в коэффициент (только с одним уровнем) для дискретной шкалы y (только с одним значением). Не имеет значения, есть ли столбец с именем "mpg" или нет, потому что вы только что передали aes() значение. ggplot не ищет столбец с именем mpg, так как он не ищет столбец с именем 1 в первом примере.

С обратными тиками вы даете ggplot то, что R распознает как имя объекта, а не только значение, подобное 1 или "some string". Итак, ggplot действительно ищет столбец с этим именем.

# both of these work
ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
ggplot(mtcars, aes(x = wt, y = `mpg`)) + geom_point()

В то время как обратные тики работают, а постоянные константы внутри aes() обычно работают, ни одно из них не рекомендуется. Предпочтительным способом установки констант является установить константы вне aes(). Это единственный способ гарантировать, что все будет хорошо работать на более сложных сюжетах. Границы, в частности, часто имеют ошибки или не дают ожидаемых результатов, если вы пытаетесь сделать странные вещи внутри aes() (особенно преобразования).

# better than above, set a constant outside of `aes()`
# Here I set y as a constant which is a bit unusual
ggplot(mtcars, aes(x = wt)) + geom_point(y = 1)
# aesthetics that are more commonly set to constants are
# size, color, fill, etc.

Для нестандартных имен столбцов aes_string() работает хорошо, а затем ожидает, что в качестве имен объектов будут указаны имена объектов. Это также хороший способ сделать что-то, если вы пишете функцию, которая создает ggplots, и нужно принимать имена столбцов в качестве аргументов.

ggplot(mtcars, aes_string(x = "wt", y = "mpg")) + geom_point()
# or, in a variable
my_y_column = "mpg"
ggplot(mtcars, aes_string(x = "wt", y = my_y_column)) + geom_point()

Еще один приятный пример, начинающий выглядеть под капотом, благодаря @TheTime:

В конце концов, ggplot необходимо оценить все, что будет сделано с помощью eval. Рассмотрим следующее:

a <- 1

eval(parse(text="a"))
# [1] 1

eval(parse(text='"a"'))
# [1] "a"

eval(parse(text="`a`"))
# [1] 1