Alex Alex - 2 months ago 19
R Question

Add secondary X axis labels to ggplot with one X axis

**Edit, there are two great solutions here, one is marked as the answer, but @hrbrmstr provides a great solution combining two ggplots which works well for this simple plot.*

Here's the code

breaks.major <- c(0,15,37.5,52.5,67.5,82.5,95,100) #defines the midpoints of the categories (label locations)
breaks.minor <- c(30,45,60,75,90) #defines the edges of the categories (second label set I need)
labels.minor <- c("","Extremely \nDissatisfied","Dissatisfied","Uncertain","Satisfied","Very \nSatisfied","Extremely \nSatisfied","")
lims =c(0,100)
g <- ggplot(mpg, aes(class))+
geom_bar()+
coord_flip()+
scale_y_continuous(limit = lims, minor_breaks = breaks.minor, breaks = breaks.major, labels = labels.minor) +
theme(panel.grid.major.x = element_blank()) +
theme(panel.grid.major.y = element_blank()) +
theme(axis.ticks.x=element_blank()) +
theme(axis.title= element_blank())


It produces this plot:

enter image description here

I need to have two sets of X-axis labels, one showing the category names (i.e. the "satisfied" etc. that are already there via
labels.minor
), and one showing the values at the
breaks.minor
locations (corresponding to the category limits, i.e. the vertical panel grid lines). I need the current
labels.minor
labels to be below the required additional labels.

I currently do this with line breaks so that the numbers and categories are all in one long string, but the spacing gets funny with plot resizes.I could do this with text boxes (I assume), is there a way within ggplot?

Extra points if you get my current labels in the centre of their sections (e.g. "Extremely Satisfied" is off-centre)

This is my desired output (pardon my 'mspaint')

enter image description here

Answer

Something like this, perhaps. Note the setting of expand for both axes to deal with proper spacing, and positions of the category names.

The labels in your figure aren't really off-centre, they are in the centre of their category boundary. It's just that by default the axes are expanded a bit further.

If you want to get more fancy, you can draw outside of the plotting area too, but it requires a bit more fiddeling. This question should get you started.

ggplot(mpg, aes(class))+
  geom_bar()+
  geom_text(data = data.frame(br = breaks.minor), aes(y = br, label = br, x = 7.75),
            size = 4, col = 'grey30') +
  coord_flip()+
  scale_y_continuous(limit = lims, minor_breaks = breaks.minor, 
                     breaks = breaks.major, labels = labels.minor, 
                     expand = c(0, 0)) +
  scale_x_discrete(expand = c(0.05, 0)) +
  theme(panel.grid.major.x = element_blank()) +
  theme(panel.grid.major.y = element_blank()) +
  theme(axis.ticks.x=element_blank()) +
  theme(axis.title= element_blank())

enter image description here