4

Is there a way to colour the names or strip backgrounds (not the backgrounds of the actual grids, as has been answered in this post: Conditionally change panel background with facet_grid?) of the facets in ggplot2's facet_grid?

In the following example:

#create simple dataframe for plotting
xy <- data.frame(x = rep(1:10, times=3), y = rep(10:1, times=3), type = rep(LETTERS[1:2], each=5), type2 = rep(LETTERS[3:5], each=10), category = rep(c("control", "exp", "control"), each=10))
xy
#create base plot
plot <- ggplot(data = xy)+
geom_point(aes(x = x, y = y))+
facet_grid(type ~ type2)

#plot base plot   
plot

Is there a way to colour the text or the background of theme(strip.text.x = element_text(size = 11, face="bold")) (?strip.background.x?) depending upon a categorical variable (for example, "category" in the data frame I have specified above, so all the controls have a red strip, all of the exp - a green one)?

Thanks in advance!

PS What I'm actually trying to do is present the results of a biological experiment:

  • two boxplots for every gene to show the variability; gene name is in the strip

  • the background of the grid is either white or grey, with grey showing genes which are controls

  • I'd like to use the colour of the text in the header to denote whether the gene is significant or not in my experiment (I need to show both the validated and non-validated genes in the same plot)

Community
  • 1
  • 1
dvanic
  • 545
  • 1
  • 4
  • 17

1 Answers1

4

@Roland taught me to hack around with the grid graphics objects on this question:

Using his advice, you can (hackily) traverse the complex grob objects and alter elements at will (but remember ggplot was kinda designed to take those decisions out of your hands for very good reason - you might make some bad graphical design choices!).

Try and work out how the below works and you will be able to extend it to change all manner of other elements. The $gp is basically the grid equivalent of par options for base plotting.

gplot <- ggplotGrob( plot )
nms <- lapply( gplot$grobs , function(x) names( x[]$children ) )
grbs <- which( sapply( lapply( nms , function(x) grepl( "strip.background.rect" , x ) ) , any ) == 1 )
cl <- c("#2b8cbe","#fc9272","#2b8cbe")
for ( i in 1:length(grbs) ){
    col <- cl[i]
    i <- grbs[i]
    gplot$grobs[[i]]$children[[1]][]$gp$fill <- col

}
require(gridExtra)
grid.arrange( gplot )

enter image description here

Community
  • 1
  • 1
Simon O'Hanlon
  • 58,647
  • 14
  • 142
  • 184
  • @simon-ohanlon Thank you! That works, but unfortunately I have no idea what that code is doing. I can't seem to google properly to understand how to parse a ggplotGrob object - are there any tutorials? What are the 20 grobs that I get when I do: gplot$grobs? – dvanic Mar 19 '14 at 06:14
  • Then I somehow find their children, which are what? nms <- lapply( gplot$grobs , function(x) names( x[]$children ) ) – dvanic Mar 19 '14 at 06:16
  • Then I use grep to find the indexes of the grobs which have children which have names containing strip.background.rect And then I assigne colours. And then what happens in the loop? – dvanic Mar 19 '14 at 06:16
  • Also, I want to play around with strip_text_x and change the colour of the words. Which grob/grep string should I use? – dvanic Mar 19 '14 at 06:18
  • The grobs are all elements which make up the plot. I'm afraid I don't have a good idea of how they are partitioned and my knowledge is based solely on trial and error. The children are exactly that, they are elements of the plot, which belong to top-level elements. I assume so that you can set the plot co-ordinates of the top-level object and all children below also move according to the top level. The `grep` to get the `grob` relating to text is `"strip.text.x.text"` and for the `A` and `B` it's `"strip.text.y.text"` (examine the `ams` object). I hope that helps. – Simon O'Hanlon Mar 19 '14 at 09:24
  • @simon-ohanlon, something has changed in ggplot or ... and this does not work anymore. Any suggestions? thanks – Alfonso Dec 09 '19 at 15:56