R ggplot2奇怪的行为.看起来它通过引用传递

Dan*_*tti 5 r ggplot2

我正在尝试复制ggplot对象,然后将新复制对象的某些属性更改为,例如,将颜色线更改为红色.

假设这段代码:

df = data.frame(cbind(x=1:10, y=1:10))
a = ggplot(df, aes(x=x, y=y)) + geom_line()
b = a
Run Code Online (Sandbox Code Playgroud)

然后,如果我改变变量行的颜色 a

a$layers[[1]]$geom_params$colour = "red"
Run Code Online (Sandbox Code Playgroud)

它也改变了颜色 b

> b$layers[[1]]$geom_params$colour 
[1] "red"    # why it is not "black"?  
Run Code Online (Sandbox Code Playgroud)

我希望我可以有两个不同的对象ab不同的特征.因此,为了以正确的方式执行此操作,我需要再次调用绘图以供b使用b = ggplot(df, aes(xy, y=z)) + geom_line().但是,此时在算法中,无法知道绘图命令ggplot(df, aes(x=x, y=y)) + geom_line()

你知道这有什么问题吗?ggplot对象是以不同的方式处理的吗?

谢谢!

MrF*_*ick 7

这里的问题是ggplot使用proto库来模仿OO风格的对象.该proto库依赖于环境来收集对象的变量.环境通过引用传递,这就是您看到自己行为的原因(也是没有人建议以这种方式更改图层属性的原因).

无论如何,从proto文档中调整一个例子,我们可以尝试对ggplot对象的laters进行深度复制.这应该"断开"它们.这是一个辅助函数

duplicate.ggplot<-function(x) {
    require(proto)
    r<-x
    r$layers <- lapply(r$layers, function(x) {
        as.proto(as.list(x), parent=x)
    })
    r
}
Run Code Online (Sandbox Code Playgroud)

所以,如果我们跑

df = data.frame(cbind(x=1:10, y=1:10))
a = ggplot(df, aes(x=x, y=y)) + geom_line()
b = a
c = duplicate.ggplot(a)

a$layers[[1]]$geom_params$colour = "red"
Run Code Online (Sandbox Code Playgroud)

然后绘制所有三个,我们得到

在此输入图像描述

这表明我们可以独立于"a"改变"c"