1

How does one add a second axis label to facetted plots? I realize in most cases they should be the same, but I have a top row with skill metrics for different models while the bottom row is the difference in skill so I'd like to include bquote(Delta*.(costlong)) below the existing axis label, and to the left of the 2nd row of facets. I've tried

`labs(y=bquote(Delta*.(costlong)*"                      "*.(costlong)*"               "))+` 

but its impossible to center well and it moves when exporting.

I've also played with

+annotation_custom(textGrob('bquote(Delta*.(costlong))),xmin=-20,xmax=-10,ymin=0,ymax=.2)

but it doesn't show up. I am limiting my x axis from 0 to 160.

here is some data and plotting code:

costlong=bquote(r^2)
skill.m=data.frame(doy=seq(1,160),yr=2000:2001,variable=factor(c('skill_phvfull','skill_phvrcnfull','fulldiff'),levels=c('skill_phvfull','skill_phvrcnfull','fulldiff')),value=runif(2*3*160,0,.6))
skill.m$set=ifelse(grepl('skill',as.character(skill.m$variable)),'data','diff')
skill.m$set=as.factor(skill.m$set)
skill.m[grepl('diff',as.character(skill.m$variable)),'value']=skill.m[grepl('diff',as.character(skill.m$variable)),'value']/3
ggplot(skill.m)+      
     geom_point(aes(x=as.numeric(doy),y=value,colour=variable),alpha=.75,size=1)+
     facet_grid(set~yr,scale='free',space='free')+
     labs(y=costlong)+
     scale_colour_brewer(name='',palette='Set1',labels=c('PHV (blended)','PHV+RCN (blended)','Blended Skill Difference'))+
     scale_x_continuous('day of year',limits=c(1,160),labels=c(1,seq(30,160,30)),breaks=c(1,seq(30,160,30)))+
     scale_y_continuous(breaks=seq(0,.7,.1),labels=seq(0,.7,.1))+
     guides(colour=guide_legend(override.aes=list(alpha=1,size=2)))+
     theme_bw()+
     theme(axis.line=element_line(colour='grey10'),
           strip.background=element_rect(fill='white',colour='white'),
           strip.text=element_text(face='bold',size='12'),
           axis.text.x=element_text(size=8,angle=90,hjust=1,vjust=.5),
           axis.text.y=element_text(size=8,angle=0),
           legend.key=element_rect(colour='white'),
           legend.position = "bottom", 
           legend.box = "horizontal")

any suggestions?

Dominik
  • 782
  • 7
  • 27
  • what do you try to achieve? adding a second axis label on the ordinate or the abscissa? only a label or the values? giving the plot of what you have and a gimped/toshop/paint circle of the missing element would be helpful! – Colonel Beauvel Apr 13 '15 at 18:44

1 Answers1

2

One way is to use gtable functions. Draw the ggplot with a blank y label. Then convert the ggplot to a grob, construct two text grobs for the two labels (the upper component and the lower component), then insert the text grobs into the layout.

library(ggplot2)
library(gtable)
library(grid)

costlong=bquote(r^2)
skill.m=data.frame(doy=seq(1,160),yr=2000:2001,variable=factor(c('skill_phvfull','skill_phvrcnfull','fulldiff'),levels=c('skill_phvfull','skill_phvrcnfull','fulldiff')),value=runif(2*3*160,0,.6))
skill.m$set=ifelse(grepl('skill',as.character(skill.m$variable)),'data','diff')
skill.m$set=as.factor(skill.m$set)
skill.m[grepl('diff',as.character(skill.m$variable)),'value']=skill.m[grepl('diff',as.character(skill.m$variable)),'value']/3

p = ggplot(skill.m)+      
     geom_point(aes(x=as.numeric(doy),y=value,colour=variable),alpha=.75,size=1)+
     facet_grid(set~yr,scale='free',space='free')+
     labs(y="")+
     scale_colour_brewer(name='',palette='Set1',labels=c('PHV (blended)','PHV+RCN (blended)','Blended Skill Difference'))+
     scale_x_continuous('day of year',limits=c(1,160),labels=c(1,seq(30,160,30)),breaks=c(1,seq(30,160,30)))+
     scale_y_continuous(breaks=seq(0,.7,.1),labels=seq(0,.7,.1))+
     guides(colour=guide_legend(override.aes=list(alpha=1,size=2)))+
     theme_bw()+
     theme(axis.line=element_line(colour='grey10'),
           strip.background=element_rect(fill=NA,colour=NA),
           strip.text=element_text(face='bold',size='12'),
           axis.text.x=element_text(size=8,angle=90,hjust=1,vjust=.5),
           axis.text.y=element_text(size=8,angle=0),
           legend.key=element_rect(colour='white'),
           legend.position = "bottom", 
           legend.box = "horizontal")

# Convert the plot to a grob
gt = ggplotGrob(p)

# Check the layout
gtable_show_layout(gt)  # To manually find the row and column for the labels

# Construct text grobs - one for each label
labL = textGrob(expression(bold(Delta * r^2)), rot = 90,
        gp = gpar(fontsize = 12))
labU = textGrob(expression(bold(r^2)), rot = 90,
        gp = gpar(fontsize = 12))

# Insert the text grobs into the layout
gt <- gtable_add_grob(gt, labL, t = 9, l =  2)
gt <- gtable_add_grob(gt, labU, t = 7, l =  2)

# Make the column a little wider
gt$widths[2] = unit(2, "lines")

# Draw it
grid.newpage()
grid.draw(gt)

enter image description here

Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
  • Thanks! Don't have time to play with this until next week but it looks like what I'm was after. Great example of using grobs too...I was trying to make the top and bottom graphs independently originally but couldn't figure out how to control the graph sizes. – Dominik Apr 16 '15 at 23:56
  • @Dominik You can draw the graphs separately, then adjust their sizes - see [this answer](http://stackoverflow.com/questions/23863345/set-ggplot-plots-to-have-same-x-axis-width-and-same-space-between-dot-plot-rows/23875319#23875319) – Sandy Muspratt Apr 17 '15 at 03:29