Konrad
Konrad

Reputation: 18657

How to align title and subtitle in ggplot2 when generated via expression

I'm using the code below to generate a simple box plot in ggplot2:

# Libs data
data("mtcars"); require(ggplot2); require(ggthemes)
# Chart
ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)),
               fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle("WT by AM") +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid",
                                  size = 0.5),
        panel.grid = element_line(colour = "gray"))

The generated chart is fairly straightforward: First chart

Task

I would like to add a subtitle to my chart and have some control over how it's rendered. I'm following this discussion and with use of the code:

# Chart
ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)),
               fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle(expression(atop("WT by AM", 
                          atop(italic("Some crucial note that has to be here"), "")))) +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid",
                                  size = 0.5),
        panel.grid = element_line(colour = "gray"))

I get the following chart: second attempt


This looks really bad, and I would like to change a few things:

  1. Make both subtitle and the title left-justified
  2. Reduce the white space between the two lines
  3. Keep the font bold

Attempts

I tried different things, like for instance the code below:

ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)),
               fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle(expression(atop("WT by AM", 
                          atop(italic("Stupid note"), "")))) +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid",
                                  size = 0.5),
        panel.grid = element_line(colour = "gray"),
        plot.title = element_text(size = 16, colour = "black", hjust = -1))

but it hides the title entirely:

missing title

Upvotes: 5

Views: 8421

Answers (3)

A Duv
A Duv

Reputation: 403

Does it have to use the "expression" command? I was doing this in ggplot2, but I imagine this would work for ggplot since they're both using plotmath.

You can use bquote and atop to add spaces based upon the length of the difference in strings. You can source things from the environment via .() in bquote's paste.

bquote(atop(
       paste("WT by AM", .(paste0(replicate(nchar("Some Crucial Note that Has to Be Here") - nchar("WT by AM"), " "), collapse = ""), 
       paste("Some Crucial Note that Has to Be Here")
            ) 
       )

As for adjusting for the different sizes of the spaces (due to font size), I'd just multiply the expression for length in replicate by a number (use floor or ceiling if you get a fraction).

EDIT: However, the characters " " and "a" have different lengths when plotted, so even having the # of spaces as the difference in string lengths isn't perfect.

Upvotes: 1

Carolyn W Clayton
Carolyn W Clayton

Reputation: 93

There is a new version of ggplot2 (2.1.0.9000+) currently on Github that solves your problem. For more information, see Bob Rudis' vignette.

devtools::install_github("hadley/ggplot2")  # Until the new version is available on CRAN
library(ggplot2)
library(ggthemes)  # Only necessary because the OP used theme_gdocs()

ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)), fill = "gray87") +
  xlab("AM") +
  ylab("WT") +
  theme_gdocs() +
  ggtitle("WT by AM", subtitle = "pearl of wisdom") +  # subtitle is a new argument. Both are now left-justified by default
  theme(plot.title=element_text(margin=margin(b=0), size = 20), plot.subtitle=element_text(margin=margin(t=5, b = 10)))  # Changing the size and margins of the title and subtitles to give the OP some options.

Title and Subtitle Image

Upvotes: 4

C8H10N4O2
C8H10N4O2

Reputation: 19045

From the "it's stupid but it works" file, you can add spaces to the right of center to force left alignment. The right number of spaces could be determined using math, but I couldn't see how to pass a string variable back into atop.

# Chart
ggplot(data = mtcars) +
  geom_boxplot(aes(y = wt, x = as.factor(am)), fill = "gray87") +
  xlab("AM") + ylab("WT") + theme_gdocs() +
  ggtitle(expression(atop("WT by AM                            ", 
                          atop(italic("Some crucial note that has to be here"), "")))) +
  theme(axis.title.y = element_text(angle = 90),
        axis.ticks = element_line(colour = "black", linetype = "solid", size = 0.5),
        panel.grid = element_line(colour = "gray"))

enter image description here

Upvotes: 3

Related Questions