8

I have a problem with ggplot title positioning. When I use hjust argument to slide title a bit right, both lines undesirably slide left and right. I want them one under the other. drawlabel(),annototations are not useful for my case, because they depend on x and y axis and their units(date,currency,kg) which mean every time I have to adjust them. I want unique coordinate system, whatever I am plotting I can easily use same place for different plots.

An undesired example with code is shown below.

set.seed(10)
df <- data.frame(x=1:10,y=round(rnorm(10)*1:10,2))
ggplot(df,aes(x=x,y=y))+
 geom_line(size=0.75)+
 labs(title = 'Here comes my title like that some words\nand my second line title')+
 theme(
   plot.title.position = 'plot',
   plot.title = element_text(hjust = 0.075)
 )

Undesirable plot

enter image description here

Desirable plot

enter image description here

user20650
  • 24,654
  • 5
  • 56
  • 91
badalovi
  • 124
  • 8
  • possibly related https://stackoverflow.com/questions/56662815/unequal-horizontal-adjustment-to-title-lines-in-ggplot – Matias Andina Jan 03 '21 at 17:22
  • I also took a glance at the link you provided. I do not think they refer to my problem. Here I want to slide both lines a bit right, both of them lose their starting point. But solutions in the link only refer to fixed default title place. – badalovi Jan 03 '21 at 17:35
  • 2
    After having a look at the issue I don't think that this is possible using default ggplot options. If you want both lines left aligned (one under the other) you have to use `hjust=0`. For the positioning ggplot only offers the two options `plot` and `panel` (I tried to adjust the margin but this only allows for adjusting top and bottom margins, while left and right have no effect). See also https://github.com/tidyverse/ggplot2/issues/3252 for a discussion of this issue. – stefan Jan 03 '21 at 18:00
  • also related: https://stackoverflow.com/questions/47523389/ggplot2-multiline-title-different-indentations?noredirect=1&lq=1 – tjebo Jan 04 '21 at 00:35
  • You might find some workarounds with `cowplot`. I posted a question a while ago that might help in going that route https://stackoverflow.com/q/50973713/5325862 – camille Jan 06 '21 at 14:35

3 Answers3

6

I agree with @stefan in the comments that there appears to be no way to do this with theme.

One hackish approach is to remove your hjust change and manually move the position of the title by editing the grid layout.

library(ggplot)
library(grid)
p <- ggplot(df,aes(x=x,y=y)) +
  geom_line(size=0.75) +
  labs(title = 'Here comes my title like that some words\nand my second line title') +
  theme(plot.title.position = 'plot')
grob <- ggplotGrob(p)
grob$layout[grob$layout$name == "title","l"] <- 4.5
grid.newpage()
grid.draw(grob)

enter image description here

You can change 4.5 as necessary for the desired effect.

Ian Campbell
  • 23,484
  • 14
  • 36
  • 57
  • I actually found this solution, however problem here is that when you change **4.5** argument to for example 4 or 2 or 5.5 it does not change as expected. Only changes to particular places. I do not know how can I add image on comment. – badalovi Jan 03 '21 at 18:43
  • @badalovi; if you look at the `l`eft column of `grob$layout` you wil get an idea of what value to use i.e. using `3` would align it with the y-axis label is perhaps sensible, or the panel use `5` etc – user20650 Jan 03 '21 at 19:15
5

ggtext provides tools that make it a bit easier to muck about with text. In the example below, using the <br> to add a newline we can then render this with the theme parameter element_textbox_simple (with a little padding around the text).

library(ggplot2)
library(ggtext)

set.seed(10)
df <- data.frame(x=1:10,y=round(rnorm(10)*1:10,2))

ggplot(df,aes(x=x,y=y))+
 geom_line(size=0.75)+
 labs(title = 'Here comes my title like that some words <br> and my second line title') +
 theme(
    plot.title.position = "plot",
    plot.title = element_textbox_simple(padding = margin(5.5, 5.5, 5.5, 5.5))
 )
user20650
  • 24,654
  • 5
  • 56
  • 91
  • Thank you for the solution you provide. This is one of the straightforward approaches. But if I am not mistaken it depends on margins or fixes margins. Which means that I can not change margins for another reason, right? – badalovi Jan 03 '21 at 20:03
  • @badalovi; `element_textbox_simple` takes a margin argument if you want to manually change things.Ian's answer provides a way to align the title with the other grobs using the indices in the gtable which you may find easier but if you additionally want to format individual words / sections of words (i.e. colour / bold / underline etc) then this answer will make things a bit easier. – user20650 Jan 03 '21 at 20:51
  • I see your point @user20650. Thank you for your attention and for your time. – badalovi Jan 04 '21 at 21:10
2

I might miss the obvious, but a simple option is to use a subtitle :)

Now, the indentation with hjust with title and subtitle is also NOT the same, however, it seems to be a constant! Weirdly this is totally dependent on your device. For example, in my RStudio Viewer, I need a constant of ~2.1, for ggsave ~1.49, and with reprex, I need 1.525 (see the example). However, once found the constant, it is actually fairly consistent. At least - for me here.

Works also for negative hjust!


library(ggplot2)
set.seed(10)
df <- data.frame(x = 1:10, y = round(rnorm(10) * 1:10, 2))

p <- ggplot(df, aes(x, y)) +
  labs(
    title = "Here comes my title like that some words",
    subtitle = "and my second line title"
  )

hjusttitle <- 0.175

p +
  theme(
    plot.title = element_text(hjust = hjusttitle, size = 14),
    plot.subtitle = element_text(hjust = hjusttitle / 1.525, size = 14)
  )


hjusttitle <- -0.15

p +
  theme(
    plot.title = element_text(hjust = hjusttitle, size = 14),
    plot.subtitle = element_text(hjust = hjusttitle / 1.525, size = 14)
  )


hjusttitle <- 1

p +
  theme(
    plot.title = element_text(hjust = hjusttitle, size = 14),
    plot.subtitle = element_text(hjust = hjusttitle / 1.525, size = 14)
  )

Created on 2021-01-04 by the reprex package (v0.3.0)

tjebo
  • 21,977
  • 7
  • 58
  • 94
  • 1
    This looks pretty straight-forward solution. Thank you. I do not want to be shown a person does not like anything, however this also limits you using subtitle as far as I know ggplot2 allows you to use only one title and one subtitle. – badalovi Jan 04 '21 at 21:07