简体   繁体   中英

Layer appending operator for ggplot2

I love ggplot2 , but I'd prefer not to write myplot <- myplot + each time I add a layer. For example,

# Load library
library(ggplot2)

# Create plot
myplot <- ggplot(iris) 
myplot <- myplot + geom_point(aes(Sepal.Length, Sepal.Width))
myplot <- myplot + ggtitle("This is a plot")
myplot <- myplot + theme_dark()
myplot

So, I wanted to create something similar to the additive compound assignment operator in C ( += ).

# Operator for appending layer
`%+=%` <- function(g, l){
  eval.parent(substitute(g <- g + l))
}

# Test appending function
myplot2 <- ggplot(iris) 
myplot2 %+=% geom_point(aes(Sepal.Length, Sepal.Width))
myplot2 %+=% ggtitle("This is a plot")
myplot2 %+=% theme_dark()
myplot2

Created on 2019-12-20 by the reprex package (v0.3.0)

As you can see, it gives the same result as the longhand syntax. This is approach is adapted from a solution given here to a different question and is accompanied by a word of warning; however, it's not clear to me why this is potentially problematic.

My question: what are the potential detrimental or unexpected side effects of defining an operator like above? Is there a better way of achieving the same result?

The only downside I can honestly say is that your constructor is not as flexible as ggplot's. ggplot already has an overloaded operator + which doesn't work intuitively with your function. Take this for an example:

gg <- ggplot(iris)
gg %+=% geom_point(aes(Sepal.Length, Sepal.Width)) + theme_dark() #plots similar to your answer
   # only geom_point was added to gg variable
   #in other words the expression above is doing this
gg <- ggplot(iris)
gg <- gg + geom_point(aes(Sepal.Length, Sepal.Width))
gg + theme_dark()

This is a result of Infix functions which are always evaluated left to right. Thus unless you were able to capture the rest of the expression then there is little hope with using your function with ggplot's +

In it's current state you are only able to assign a layer one at a time which is arguably less efficient/tidy than doing

gg <- gg + geom_point(aes(Sepal.Length,Sepal.Width)) +
    ggtitle("This is a plot") +
    theme_dark()

It is also unusable with itself, but if you recode it as such:

`%+=%` <- function(g, l) {
  UseMethod("%+=%")
}

`%+=%.gg` <- function(g, l){
  gg.name <- deparse(substitute(g))
  gg.name <- strsplit(gg.name, split = "%+=%", fixed= T)[[1]][1]
  gg.name <- gsub(pattern = " ", replacement = "", x = gg.name)
  gg <- g +l
  assign(x = gg.name, value = gg, envir = parent.frame())
}

gg <- ggplot(iris)
gg %+=% geom_point(aes(Sepal.Length, Sepal.Width)) %+=% theme_dark() #will now save left to right

I am really just being nit picky, but if your intent is to use this by adding a layer once at a time, then by all means your original function seems to work fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM