8

I have a two facet plots created in ggplot2. I would like to add an arrow outside of the plot area. Multiple questions tried to address this: How to draw lines outside of plot area in ggplot2? Displaying text below the plot generated by ggplot2

but I can't make my example work. Also, I hope there is an easier way to accomplish this?

I tried to increase plot.margins and to use coord_cartesian(), but neither helped.

enter image description here

Instead, I want:

enter image description here

My dummy example:

# read library to assess free data
library(reshape2)
library(ggplot2)


ggplot(tips,
       aes(x=total_bill,
           y=tip/total_bill)) + 
  geom_point(shape=1) +
  facet_grid(. ~ sex) +
  # define the segment outside the plot
  geom_segment(aes(x = 10, 
                   y = -0.25, 
                   xend = 10, 
                   yend = 0),
               col = "red",
               arrow = arrow(length = unit(0.3, "cm"))) +
  theme_bw() +
  # limit the displayed plot extent
  coord_cartesian(ylim = c(0, 0.75)) +
  # increase plot margins - does not help
  theme(plot.margin = unit(c(1,1,1,0), "lines"))
maycca
  • 3,848
  • 5
  • 36
  • 67

2 Answers2

11

You can draw outside the panel using the argument clip="off" in coord_cartesian. I also use the expand argument of scale_y to start the y-axis at zero. There is a bit a manual selection over the y start position.

So your example

library(reshape2)
library(ggplot2)

ggplot(tips,
       aes(x=total_bill,
           y=tip/total_bill)) + 
  geom_point(shape=1) +
  facet_grid(. ~ sex) +
  annotate("segment", x=12, y=-0.05, xend=12, yend=0,
               col="red", arrow=arrow(length=unit(0.3, "cm"))) +
  scale_y_continuous(expand=c(0,0))+
  theme_bw() +
  coord_cartesian(ylim = c(0, 0.75), clip="off") +
  theme(plot.margin = unit(c(1,1,1,0), "lines"))

(I changed geom_segment to annotate as you were not mapping aesthetics)

Which produces

enter image description here

user20650
  • 24,654
  • 5
  • 56
  • 91
  • 1
    Thank you for your answer @user20650! Please, can you include also a resulting plot in it? Everybody than can see the resulting plot without the need to rerun the code in their R environment. – maycca Sep 24 '18 at 18:39
  • coord_cartesian is shifting some of the plotted points outside the plot area. – Herman Toothrot Oct 30 '18 at 14:26
  • what do you mean @HermanToothrot; is it that if points are right on the axes border, after using `clip` that some of the point is outside the plot panel?? or – user20650 Oct 30 '18 at 15:33
  • The points in the upper part of the plot are cut off, I had to set ylim = c(0, 1). I am just suggesting that your solution might not work for all plots. – Herman Toothrot Oct 30 '18 at 17:05
  • Hi @HermanToothrot ; ah right got you. okay yes the limits are plot specific – user20650 Oct 30 '18 at 19:39
3

This is a workaround which is not exactly super satisfying, because you will need to play around with the position of your plots. Principally it uses custom annotation, possible with cowplot

library(ggplot2) 
library(cowplot)
library(reshape2)

First define your plots, with the same coordinate limits.

p <- 
  ggplot(tips, aes(x = total_bill, y = tip/total_bill)) + 
  geom_point(shape = 1) +
  facet_grid(. ~ sex) +
  theme_bw() +
  coord_cartesian(ylim = c(0, 0.75), xlim = c(0, 50)) 

arrow_p <- 
  ggplot(tips) +
  geom_segment(aes(x = 1, y = -1, xend = 1, yend = 0),
               col = "red",
               arrow = arrow(length = unit(0.3, "cm"))) +
  coord_cartesian(ylim = c(0, 0.75), xlim = c(0,50)) +
  theme_void()

arrow_p is created on a void background for use as overlay. You can now position it where you want with:

 ggdraw() +
    draw_plot(p) +
    draw_plot(arrow_p, x = 0.10, y = 0.05) +
    draw_plot(arrow_p, x = 0.57, y = 0.05)

enter image description here

Unfortunately, you have to trial-and-error here. You can also change specify the width/height/scale parameters of draw_plot(). There might be a better way, but this is a fairly straight forward workaround...

tjebo
  • 21,977
  • 7
  • 58
  • 94