Rspacer
Rspacer

Reputation: 2429

How to add subtext to axes in ggplot2 R

For the main y-axis and x-axis, I have generic titles like "Tank's Ratio" and "Counts". I want a second line of label where I specify the ratio and counts. eg. Just below "Tank's Ratio" I want "# in water/# in sand" in a smaller font but along the y-axis. Similarly for the x-axis. Here is the basic code

data <- data.frame(set = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 4), density = c(1, 3, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3), counts = c(100, 2, 3, 76, 33, 12, 44, 13, 54, 36, 65, 1), ratio = c(1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 90, 1))

library(ggplot2)

ggplot(data, aes(x = counts, y = ratio)) + 
  geom_point() + 
  ylab("Tank's Ratio") + 
  xlab("Counts") 

Upvotes: 8

Views: 7840

Answers (3)

KoenV
KoenV

Reputation: 4283

You could use the following code, defining the margins, the axis titles and sub-titles yourself:

We use theme to increase the bottom and left margin, and to suppress the automatically generated axis titles.

We use annotate to generate the text that serves as axis title and sub-title, if necessary, the text is rotated.

We generate the plot, turn it in a grob, and with this grob we can turn of clipping, and show the plot.

g1 <- ggplot(data = data, aes(x = counts, y = ratio, group = 1)) +
  geom_point()  + 

  ## increase margin size for left and bottom and
  ## remove the axis titles
  theme(plot.margin = unit(c(1, 1, 4, 4), "lines"),
        axis.title.y = element_blank(),
        axis.title.x = element_blank() ) +

  ## define the plotting area to NOT include the annotations
  coord_cartesian(xlim = c(0, 100), ylim= c(0, 100), expand = FALSE) +

  ## annotate y axis
  annotate(geom = "text", x = -9, y = 50, label = "Tank's Ratio", angle = 90, size = 5) +
  annotate(geom = "text", x = -5, y = 50, label = "#in water/#in sand", angle = 90, size = 4) +

  ## annotate x axis
  annotate(geom = "text", x = 50, y = -5, label = "Counts", size = 5) +
  annotate(geom = "text", x = 50, y = -9, label = "#in water/#in sand", size = 4)

## turn off  clipping for axis extra labels
g2 <- ggplot_gtable(ggplot_build(g1))
g2$layout$clip[g2$layout$name == "panel"] <- "off"
grid::grid.draw(g2)

This yields the following picture:

enter image description here

Please let me know whether this is what you want.

Upvotes: 2

NelsonGon
NelsonGon

Reputation: 13319

You can add x and main titles.

EDIT: This is ridiculously slooow!

  #library(extrafont)
#loadfonts(dev="win")
library(tidyverse)
data %>%
ggplot(aes(x=counts, y=ratio)) + geom_point() +
labs(y=expression(atop(bold("Tank's Ratio"),atop(italic("#in water #in sand")))))+
  theme_minimal()+
  theme(axis.title.y = element_text(size=15,family="Comic Sans MS"))

enter image description here

ORIGINAL:

library(tidyverse) 

      data %>%
    ggplot(aes(x=counts, y=ratio)) + geom_point() +
    labs(y="Tank's Ratio \n #in Water#in sand")

Upvotes: 3

Adela
Adela

Reputation: 1797

It's not the most elegant solution, but hope it helps:

library(ggplot2)
library(gridExtra)
library(grid)

First, create plot without ylab:

g <- ggplot(data, aes(x = counts, y = ratio)) + 
  geom_point()  +
  ylab("") + 
  xlab("Counts") 

Then add subtitle for both axis:

g2 <- grid.arrange(g, 
                   bottom = textGrob("in water/ # in sand", 
                                     x = 0.55, y = 1, gp = gpar(fontsize = 9)),
                   left = textGrob("in water/ # in sand",  rot = 90, 
                                   x = 1.5, gp = gpar(fontsize = 9)))

And finally, add description of y-axis

grid.arrange(g2, 
             left = textGrob("Tank's Ratio",  rot = 90, 
                             x = 1.7, gp = gpar(fontsize = 12)))

enter image description here

Upvotes: 2

Related Questions