0

This is what I want:

gg <- ggplot(mpg,aes(displ,cty,color=as.factor(cyl))) + geom_point() + 
   labs(title = "Cars",subtitle= "engine size vs mpg") + 
   theme(plot.subtitle = element_text(vjust=-7,hjust = .01),
       plot.title = element_text(vjust=-5))
gg

plot of mpg data showing subtitle pushed down into plot panel It pushes the titles down such that the subtitle is just within the plot panel.

I would like to "pre-bake" a parameter-less theme_nudge() function that intelligently decides on the vjust parameter. This requires understanding of the plot panel range. I can extract the range from the gg object AFTER it's rendered (extract plot range from ggplot object) but I want to do it on the fly. It would then look like this:

theme_nudge <- function(...){
   #probably something like
   my_vjust <- -(computed_range_y * .1)
   ggplot2::theme(plot.subtitle = element_text(vjust=my_vjust,hjust=.1),
                  plot.title = element_text(vjust=my_vjust*.7),
                  ...)
}

gg <- ggplot(mpg,aes(displ,cty,color=as.factor(cyl))) + geom_point() + 
   labs(title = "Cars",subtitle= "engine size vs mpg") + 
   theme_nudge()

What is computed_range_y? Is that possible? Thanks.

Art
  • 1,165
  • 6
  • 18

1 Answers1

4

From my understanding of the ggplot2 internals I think that achieving your desired result via theme() requires some (or a lot of effort). But of course I might be wrong.

Instead, if you just want to place your substitle in the "top-left" of the plot area then I would go for a custom function which uses annotation_custom to achieve that and which could be easily extended to add some more options, e.g. in the code below I added a padding argument to add some padding to the top and the left of the subtitle.

library(ggplot2)

nudge_subtitle <- function(subtitle, padding = 0) {
  ggplot2::annotation_custom(
    grob = grid::textGrob(
      label = subtitle,
      x = unit(0, "npc") + unit(padding, "pt"),
      y = unit(1, "npc") - unit(padding, "pt"),
      hjust = 0, vjust = 1
    )
  )
}
  
ggplot(mpg, aes(displ, cty, color = as.factor(cyl))) +
  geom_point() +
  labs(title = "Cars") +
  nudge_subtitle(subtitle = "engine size vs mpg")

stefan
  • 90,330
  • 6
  • 25
  • 51