2

I would like to know how to add a border to my plot on only one side. I have this plot:

library(ggplot2)

p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  theme_minimal() +
  labs(title = "Title",
       subtitle = "Subtitle")

p

plain plot

Created on 2019-12-21 by the reprex package (v0.3.0)

I would like to add a horizontal line above the title, like this:

enter image description here

I cannot figure out how to do this. I have tried theme(plot.background = element_rect()), but this adds a border on all sides of the plot.

In this case I would prefer not to use gridExtra:grid.arrange() or {patchwork} to add a line grob above the plot.

markus
  • 25,843
  • 5
  • 39
  • 58
Matt Cowgill
  • 659
  • 4
  • 13
  • just in case this gridExtra is different to what you were not wanting: ` `grid.arrange(p, top=linesGrob(x=0:1,y=0.5, gp=gpar(col="blue", lwd=10)), padding=unit(1, "lines"))` – user20650 Dec 21 '19 at 20:02

1 Answers1

3

This is based on answers to this question.

Note that the title = "Title" was changed to have a blank line of title text above what is printed. It is now title = "\nTitle".

It uses package grid, functions linesGrob and grid.draw.

library(ggplot2)
library(grid)

p <- ggplot(mtcars, aes(x = wt, y = mpg)) +
  geom_point() +
  theme_minimal() +
  labs(title = "\nTitle",
       subtitle = "Subtitle")

p1 <- p + annotation_custom(grob = linesGrob(y = unit(3, "lines"), 
                                             gp = gpar(col = "blue")), 
                            xmin = -Inf, xmax = Inf, ymin = Inf, ymax = Inf)

gt <- ggplot_gtable(ggplot_build(p1))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)

enter image description here

To extend the line to the margins along the x axis, also set a value of x in linesGrob. The right side value is a large integer number because apparently linesGrob doesn't accept Inf.

p2 <- p + annotation_custom(grob = linesGrob(x = unit(c(-2, 100), "lines"),
                                             y = unit(3, "lines"), 
                                             gp = gpar(col = "blue")), 
                            xmin = -Inf, xmax = Inf, ymin = Inf, ymax = Inf)

gt <- ggplot_gtable(ggplot_build(p2))
gt$layout$clip[gt$layout$name=="panel"] <- "off"
grid.draw(gt)

enter image description here

Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
  • Thank you. Before I accept the answer: do you know how to extend the line to the boundary of the plot, rather than the panel? – Matt Cowgill Dec 21 '19 at 09:56
  • @MattCowgill No, I don't. But I believe that the method used in the answer in the link shows how to draw something in any side of the panel. To *extend* a line drawn on one side might be a different problem, though. – Rui Barradas Dec 21 '19 at 09:59
  • @MattCowgill Try `linesGrob(x = unit(c(-2, 100), "lines"), etc)`. – Rui Barradas Dec 21 '19 at 12:29