Скопированный ggplot-объект частично связан с оригиналом

Чтобы изменить несколько аспектов макета графика, созданного с помощью ggplot, я сначала скопировал исходный объект ggplot в новую переменную, чтобы сохранить оригинал нетронутым. Когда я обновил копию, я заметил, что некоторые вещи также были обновлены в исходном объекте, как если бы они были связаны. Но это произошло не для всех изменений, как будто это зависит от того, какой тип параметра изменяется.

У кого-нибудь есть объяснение этому поведению и решение?

Вот пример:

library(tidyverse)

# Create ggplot-object
irisplot <- ggplot(iris, aes(x=Species, y=Sepal.Width, color=Species)) +
  geom_boxplot(outlier.alpha=0) +
  geom_jitter(width=0.5)

# Copy into new variable
newvariable <- irisplot
tracemem(irisplot)==tracemem(newvariable) # prints FALSE with rlang::duplicate(irisplot) and TRUE without
untracemem(irisplot)
untracemem(newvariable)

##### Linked: layers
# Check original outlier.alpha
irisplot$layers[[1]]$geom_params$outlier.alpha # prints 0 for me
newvariable$layers[[1]]$geom_params$outlier.alpha # prints 0 for me

# Update outlier.alpha in copy
newvariable$layers[[1]]$geom_params$outlier.alpha <- 1
tracemem(irisplot)==tracemem(newvariable)

# Check updated outlier.alpha
newvariable$layers[[1]]$geom_params$outlier.alpha # prints 1 for me
irisplot$layers[[1]]$geom_params$outlier.alpha # prints 1 for me

untracemem(irisplot)
untracemem(newvariable)

##### Not linked: labels
# Check original x-label
irisplot$labels$x # prints "Species" for me
newvariable$labels$x # prints "Species" for me

# Updated x-label
newvariable$labels$x <- "New label"

# Check updated x-label
newvariable$labels$x # prints "New label" for me
irisplot$labels$x # prints "Species" for me

Я включил tracemem, чтобы проверить, не связано ли это с общим адресом памяти изначально, но замена строки копирования на newvariable <- rlang::duplicate(irisplot) не меняет связанного поведения.

Немного связанный с этим вопрос: кажется, что это способ изменить существующий объект ggplot таким образом, перезаписав определенные параметры, но есть ли более чистый/официальный способ сделать это? Например. метки Я могу использовать тему, но как насчет специфических для геометрии вещей?

Редактировать:

Моя установка: Windows 10, R версии 3.6.1, ggplot2 3.3.2, rlang 0.4.7

Коллега у которого такой же результат: windows 10, R версия 4.0.3, ggplot2 3.3.2, rlang 0.4.7

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
99
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

ggplot2 использует среду в качестве основы для своих ggproto объектов. В R среды передаются по ссылке, поэтому вы не получаете глубокую копию при копировании ggplot. Есть несколько способов получить глубокую копию, но, пожалуй, самый простой — это unserialize(serialize(ggplot)):

library(ggplot2)

irisplot <- ggplot(iris, aes(x=Species, y=Sepal.Width, color=Species)) +
  geom_boxplot(outlier.alpha=0) +
  geom_jitter(width=0.5)

# Make a deep copy
newvariable <- unserialize(serialize(irisplot, NULL))

# objects are currently the same
irisplot$layers[[1]]$geom_params$outlier.alpha
#> [1] 0
newvariable$layers[[1]]$geom_params$outlier.alpha 
#> [1] 0

# Update outlier.alpha in copy
newvariable$layers[[1]]$geom_params$outlier.alpha <- 1

# Check updated outlier.alpha
newvariable$layers[[1]]$geom_params$outlier.alpha 
#> [1] 1
irisplot$layers[[1]]$geom_params$outlier.alpha 
#> [1] 0

Created on 2020-12-14 by the reprex package (v0.3.0)

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