ggplot2: Create an independent copy from an ggplot

2019-05-08 04:11发布

I'm not sure how to put this in OO-Speech. But when you are creating a ggplot it will be dependent from the source data.frame. So how can you save a ggplot without that dependency?

dat <- data.frame(x=runif(10),y=runif(10))  
g <- ggplot(dat, aes(x,y)) + geom_point()  
g  

dat <- NULL  
g

The second $g$ won't produce a plot hence dat is $NULL$. How can I save $g$ so that dat can be changed?

I know it is not good practice but I got some very long code on which I don't want to fiddle about.

标签: r oop ggplot2
2条回答
三岁会撩人
2楼-- · 2019-05-08 04:39

Personally, I think that @Joshua's answer is too complicated (if I'm understanding what you want to do).

I don't think it makes any sense to change the data frame stored in the plot object, since ggplot2 has a special infix operator that is specifically designed to apply a new data frame to a given plot object: %+%.

dat <- data.frame(x=runif(10),y=runif(10))  
g <- ggplot(dat, aes(x,y)) + geom_point()  
g

enter image description here

#Change the data frame
dat$y <- rexp(10)
#Replot g using the altered data frame
g %+% dat

enter image description here

This works, of course, with not just altered versions of the original data frame, but an entirely new data frame, provided it has all the required variables in it (and they are named the same).

查看更多
在下西门庆
3楼-- · 2019-05-08 04:44

I think there are several options, I show in order of my preference.

## setup
require(ggplot2)
set.seed(10) # make reproducible
dat <- data.frame(x=1:10,y=runif(10))   

My favorite option is to create a simple function wrapper to your code. Then whenever you need to change the data, just pass new data to your function, and it will give it to ggplot and create the new graph. This is flexible and fairly robust to problems. It is also extensible, in that if later you decide you would also like to be able to change the title, you can just add a title argument to your function too.

## my favorite option
myplot <- function(data) {
  ggplot(data, aes(x, y)) + geom_point()
}

## use it
myplot(data = dat)

first plot

## change it
dat <- data.frame(x = 11:20, y = runif(10))
myplot(data = dat)

second plot

Another approach is to save your call to ggplot as an expression, which is unevaluated. Then you just evaluate it whenever you want. It is almost like typing the code each time (it is different in some ways but that is the best analogy I can think of).

## not wild about this one
myplotcall <- expression(ggplot(dat, aes(x,y)) + geom_point())

## look at it (literally just the input)
myplotcall
expression(ggplot(dat, aes(x, y)) + geom_point())

## use it
eval(myplotcall)

third plot

## change it
dat <- data.frame(x = 21:30, y = runif(10))
eval(myplotcall)

fourth plot

You can change the data in the ggplot object itself. I think that this approach would be the most prone to problems as you are mucking with internals of an object that was not really intended to be changed by the user (i.e., just because we can does not mean we should). This is more appropriately done with the %+% operator (see joran's answer)

## not wild about this either
g <- ggplot(dat, aes(x,y)) + geom_point()
g ## use it

fifth plot

## change it
dat <- data.frame(x = 31:40, y = runif(10))
g$data <- dat
g

sixth plot

查看更多
登录 后发表回答