7
votes

I have a plot whose labels are factors of the form "1990-2012". They are too long and/or there are too many of them and they overlap.

enter image description here

I would like to print each label over two lines and break it after the hyphen, something like this:

enter image description here

For situations where breaking the labels into two parts would still not suffice, I would also like to know how to print only every other label.

A constraint I have is that the labelling should be done "in-place" without pre-processing of the data.frame and/or labels, though a custom function applied within the call to ggplot would be fine.

Here is the sacrosanct dataframe (cannot be altered):

    df <- structure(list(Period = structure(1:13, .Label = c("0-1000", 
    "1000-1500", "1500-1700", "1700-1820", "1820-1913", "1913-1950", 
    "1950-1970", "1970-1990", "1990-2012", "2012-2030", "2030-2050", 
    "2050-2070", "2070-2100"), class = "factor"), value = c(0.000168759866884916, 
    0.000989913144738397, 0.00159894629454382, 0.0045594248070473, 
    0.00585564273031225, 0.00932876890888812, 0.0191066122563939, 
    0.0183146076484786, 0.0130117469870081, 0.00923670910453378, 
    0.00560791817163286, 0.00272731553972227, 0.00149387241891397
    ), variable = c("World", "World", "World", "World", "World", 
    "World", "World", "World", "World", "World", "World", "World", 
    "World")), .Names = c("Period", "value", "variable"), row.names = c(NA, 
    -13L), class = "data.frame")

Here is the ggplot:

    library(ggplot2)
    p <- ggplot(data = df, aes(x = Period, y = value, group = variable)) + geom_line() + theme_bw() 

The following would work, if I had a space after the hyphen:

  library(stringr)
  p + scale_x_discrete(labels = function(x) str_wrap(x, width = 4))

[The two lines above were used to produce the second plot, after I had manually altered the dataframe to add a blank space after the date-separating hyphen, in other words, after I cheated]

The following approach to print fewer labels usually works, but fails here:

   library(scales)
   p + scale_x_discrete(breaks = pretty_breaks(n = 6)) 
1

1 Answers

7
votes

Is this what you are looking for?

p + scale_x_discrete(
  labels=function(x){
    x2 <- sub("(\\d+)\\-(\\d+)",
               "\\1\\-\n\\2",
               x)
    x2
  })

enter image description here

Actually the intermediate x2 isn't even necessary, this

p + scale_x_discrete(
  labels=function(x){
    sub("(\\d+)\\-(\\d+)","\\1\\-\n\\2",x)
  })

is a little more compact.

Edit: An even more concise solution, thanks to @jlhoward:

p + scale_x_discrete(
  labels=function(x) sub("-","-\n",x,fixed=TRUE))