jenswirf
jenswirf

Reputation: 7307

How to dynamically set theme objects in ggplot2?

I'm trying to define this function to easily set a custom theme to a ggplot, but I'm having trouble using the functions like element_blank() dynamically.. For example, specifying whether or not to have vertical gridlines as a TRUE/FALSE argument:

qplot(data=df, x=quarter, y=value, geom="line") + 
  style(grid.vertical = F)


style = function (grid.vertical = T) {
(theme_foundation() + 
 theme(
       panel.grid.major.x = ifelse(grid.vertical == T, element_line(), element_blank())
 ))}

produces..

Error in (function (el, elname)  : 
Element panel.grid.major.x must be a element_line object.

Is there a way to make this work?

Upvotes: 1

Views: 1961

Answers (2)

edvaldig
edvaldig

Reputation: 2299

This has to do with how the ggplot code is checking for types:

...
else if (!inherits(el, eldef$class) && !inherits(el, "element_blank")) {
    stop("Element ", elname, " must be a ", eldef$class, 
        " object.")
}

Since we're using the ifelse function, I think this dynamic type checking voodoo will look at ifelse as being the "element" here, so the conditions are never met since it doesn't inherit from element_blank. To solve this, just use regular if/else expression instead of ifelse:

style = function (grid.vertical = T) {
(theme_foundation() + 
 theme(
       panel.grid.major.x = if(grid.vertical == T) element_line() else element_blank()
 ))}

I had the exact same problem and this solution worked for me.

Upvotes: 1

tonytonov
tonytonov

Reputation: 25608

It seems that the error is produced by an unpleasant peculiarity of ifelse. I tried the workaround from the accepted answer there, but that did not help. So I guess the simplest way would be to switch to the regular if, though the code doesn't seem to be particularly neat.

style.if = function (grid.vertical = T) {
  t <- theme()
  if (grid.vertical) 
    t <- t + theme(panel.grid.major.x = element_line(colour = 'red'))
  else t <- t + theme(panel.grid.major.x = element_blank())
  t
}

ggplot(mtcars, aes(x=wt, y=mpg)) + geom_line() + style.if()
ggplot(mtcars, aes(x=wt, y=mpg)) + geom_line() + style.if(F)

Upvotes: 2

Related Questions