8

I drew two panels in a column using ggplot2 facet, and would like to add two vertical lines across the panels at x = 4 and 8. The following is the code:

library(ggplot2)
library(gtable)
library(grid)

dat <- data.frame(x=rep(1:10,2),y=1:20+rnorm(20),z=c(rep("A",10),rep("B",10)))

P <- ggplot(dat,aes(x,y)) + geom_point() + facet_grid(z~.) + xlim(0,10)
Pb <- ggplot_build(P);Pg <- ggplot_gtable(Pb)

for (i in c(4,8)){
    Pg <- gtable_add_grob(Pg, moveToGrob(i/10,0),t=8,l=4)
    Pg <- gtable_add_grob(Pg, lineToGrob(i/10,1),t=6,l=4)
}

Pg$layout$clip <- "off"
grid.newpage()
grid.draw(Pg)

The above code is modified from:ggplot, drawing line between points across facets. And this is the output figure.

There are two problems in this figure. First, only one vertical line was shown. It seems that moveToGrob only worked once.. Second, the shown line is not exact at x = 4. I didn't find the Pb$panel$ranges variable, so is there a way that I can correct the range as well? Thanks a lot.

Community
  • 1
  • 1
Bright
  • 83
  • 1
  • 4
  • `ggplot(dat,aes(x,y)) + geom_point() + facet_grid(z~.) + xlim(0,10) + geom_vline(xintercept = c(4, 8))` – alistaire Feb 10 '17 at 05:12
  • @alistaire Perhaps you should add this as an answer, as your solution should fix/answer the OP. – steveb Feb 10 '17 at 06:16

2 Answers2

8

Updated to ggplot2 V3.0.0

In the simple scenario where panels have common axes and the lines extend across the full y range you can draw lines over the whole gtable cells, having found the correct npc coordinates conversion (cf previous post, updated because ggplot2 keeps changing),

library(ggplot2)
library(gtable)
library(grid)

dat <- data.frame(x=rep(1:10,2),y=1:20+rnorm(20),z=c(rep("A",10),rep("B",10)))

p <- ggplot(dat,aes(x,y)) + geom_point() + facet_grid(z~.) + xlim(0,10)
pb <- ggplot_build(p)
pg <- ggplot_gtable(pb)


data2npc <- function(x, panel = 1L, axis = "x") {
  range <- pb$layout$panel_params[[panel]][[paste0(axis,".range")]]
  scales::rescale(c(range, x), c(0,1))[-c(1,2)]
}


start <- sapply(c(4,8), data2npc, panel=1, axis="x")

pg <- gtable_add_grob(pg, segmentsGrob(x0=start, x1=start, y0=0, y1=1, gp=gpar(lty=2)), t=7, b=9, l=5)

grid.newpage()
grid.draw(pg)

enter image description here

Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
baptiste
  • 75,767
  • 19
  • 198
  • 294
  • Again, sorry to bother, I can't make this work, is this outdated? "R version 3.4.1, gtable_0.2.0, ggplot2_2.2.1". [This post led me here](https://stackoverflow.com/questions/45144469/ggplot-draw-across-facets). – zx8754 Jul 17 '17 at 13:19
6

You can just use geom_vline and avoid the grid mess altogether:

ggplot(dat, aes(x, y)) + 
    geom_point() + 
    geom_vline(xintercept = c(4, 8)) + 
    facet_grid(z ~ .) + 
    xlim(0, 10)

plot with vlines

alistaire
  • 42,459
  • 4
  • 77
  • 117
  • Thanks alistaire. And beetroot is correct, I'd like two continuous lines across the facets.. – Bright Feb 10 '17 at 14:43