Сопоставления ggplot2 меняются при использовании аккуратной оценки и aes() вместо aes_string()

Я пытаюсь обновить какой-то старый код построения сюжета, который выдает сообщение:

Warning message: `aes_string()` was deprecated in ggplot2 3.0.0. Please use tidy evaluation ideoms with `aes()`

Когда я заменяю aes_string() на aes() и без кавычек !!, я начинаю получать сообщение «Ошибка: дискретное значение предоставлено для непрерывной шкалы» в неожиданных местах.

Вот упрощенный воспроизводимый пример:

# Make some test data
set.seed(1)
dat <- data.frame(x=rnorm(100),y=rnorm(100),value=rnorm(100))
xvar <- 'x'
yvar <- 'y'
cvar <- 'value'

# This works, but gives a deprecated warning for use of aes_string()
ggplot(dat,aes_string(x=xvar,y=yvar,color=cvar)) + geom_point() + scale_color_gradientn(colors = rainbow(10))

# This changes the plot to use aes() with !! instead of using aes_string()
# It fails with "Error: Discrete value supplied to continuous scale"
ggplot(dat,aes(x=!!xvar,y=!!yvar,color=!!cvar)) + geom_point() + scale_color_gradientn(colors = rainbow(10))

Я не смог понять, что вызывает это, но похоже, что сами сопоставления обрабатываются по-разному в ggplot - с aes_string() имена переменных отображаются с ~ в начале и с aes( ) и !! они не:

# Capture each plot so it can be examined
plt_working <- ggplot(dat,aes_string(x=xvar,y=yvar,color=cvar)) + geom_point() + scale_color_gradientn(colors = rainbow(10))
plt_broken <- ggplot(dat,aes(x=!!xvar,y=!!yvar,color=!!cvar)) + geom_point() + scale_color_gradientn(colors = rainbow(10))

summary(plt_working) # The second line says "mapping:  colour = ~value, x = ~x, y = ~y"
summary(plt_broken) # The second line says "mapping:  x = x, y = y, colour = value" (no ~s)

Что означает ~? В этом контексте кажется, что это не имеет ничего общего с формулами или гранями.

Почему это изменение приводит к тому, что код сюжета перестает работать, и как правильно обновить код, чтобы он продолжал работать?

Дополнительная информация: версии программного обеспечения не имеют значения — это происходит в системе Linux с R 4.2.2/ggplot2 3.4.0 и в системе MacOS с R 4.2.0/ggplot2 3.3.6.

bluemouse 24.01.2023 04:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Текущий (по состоянию на 2023 год) предпочтительный метод использования строк внутри aes() — через объект ggplot .data (спасибо Лайонелу Генри за разъяснение причин этого):

xvar <- 'x'
yvar <- 'y'
cvar <- 'value'

ggplot(dat,aes(x = .data[[xvar]], y = .data[[yvar]], color = .data[[cvar]])) + geom_point() + scale_color_gradientn(colors = rainbow(10))

Кроме того, вы можете обернуть свои строки в sym(), а затем использовать !!, чтобы развернуть их внутри aes():

set.seed(1)
dat <- data.frame(x=rnorm(100),y=rnorm(100),value=rnorm(100))
xvar <- sym('x')
yvar <- sym('y')
cvar <- sym('value')

ggplot(dat,aes(x=!!xvar,y=!!yvar,color=!!cvar)) + geom_point() + scale_color_gradientn(colors = rainbow(10))

Спасибо! Это работает, но могу ли я спросить, почему и почему это необходимо? Я не являюсь большим пользователем tidyverse, но когда я использовал другие функции tidyverse, такие как collect() и pivot_longer(), они работали с ними !! без необходимости sym(). Как узнать, когда использовать sym(), а когда нет?

bluemouse 24.01.2023 04:25

Я согласен, что это кажется несовместимым с другими функциями tidyverse, но как это может работать по-другому? По умолчанию aes() пытается оценить эстетические сопоставления (например, color = value) как строки без кавычек. Таким образом, чтобы заменить здесь строки, необходимо ввести слой квазицитирования. Вы также можете заменить строки немного меньшим набором текста с помощью объекта .data, который я добавил в ответ.

jdobres 24.01.2023 04:47

Спасибо! Боюсь, я все еще не понимаю - откуда мне знать, когда я должен использовать !! и когда я должен использовать !!sym() ? Я просто запоминаю !!sym() как особую вещь, которую нужно делать в aes(), или есть другие ситуации, когда мне может понадобиться сделать это таким образом?

bluemouse 24.01.2023 04:51

@jdobres прав в отношении неоднозначности строк в этом случае. В этом разница между маскированием данных и аккуратным выбором, только последний может интерпретировать строки. Это различие должно быть указано в документации к функции и является фундаментальным свойством, влияющим на использование аргумента: при выборе вы используете c() для нескольких столбцов, можете сопоставляться с starts_with() и т. д. Кстати, теперь мы избегаем !!, где можем. Мы рекомендуем либо all_of() в функциях выбора, таких как pivot_longer(), либо .data[[my_string]] в функциях маскирования данных.

Lionel Henry 24.01.2023 05:27

@LionelHenry спасибо!! Термин «маскирование данных» привел меня к следующему: dplyr.tidyverse.org/reference/dplyr_data_masking.html, который я опубликую позже для всех, кто погуглит. Я все еще не совсем уверен, почему !!sym(xvar) работал, но я думаю, что по крайней мере понимаю, почему .data[[xvar]] является предпочтительным способом сделать это.

bluemouse 24.01.2023 10:13

да, понимание метапрограммирования и внедрение символов/вызовов/квазур оказалось слишком сложным для большинства пользователей, поэтому сейчас мы сосредоточились на более простых шаблонах в нашей документации. Если вы хотите читать дальше, на веб-сайте rlang также есть документация: rlang.r-lib.org/reference/topic-data-mask-programming.html

Lionel Henry 24.01.2023 10:32

Другие вопросы по теме