ggplot, рисование нескольких линий по граням

Я нарисовал две панели в столбце с помощью фасета ggplot2 и хотел бы добавить две вертикальные линии через панели при x = 4 и 8. Следующий код:

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)

вышеуказанный код изменен от:ggplot, проводя линию между точками по граням. И this is the output figure.

на этом рисунке есть две проблемы. Сначала была показана только одна вертикальная линия. Кажется, что moveToGrob только один раз работал.. Во-вторых, показанная линия не является точной при x = 4. Я не найдите Pb$panel$ranges переменная, так есть ли способ, которым я могу исправить диапазон? Большое спасибо.

2 ответов


обновлено до ggplot2 V3.0.0

в простом сценарии, где панели имеют общие оси, а линии простираются через весь диапазон y, вы можете рисовать линии по всем ячейкам gtable, найдя правильное преобразование координат npc (cf предыдущий пост, обновленный, потому что ggplot2 продолжает меняться),

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


вы можете просто использовать geom_vline и избежать grid бардак в целом:

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

plot with vlines