ggplot2 добавляет аннотацию, охватывающую грани фасета - PullRequest
0 голосов
/ 28 июня 2018

Я хочу нарисовать прямоугольную аннотацию, которая будет охватывать границы фасетов в ggplot.

library(ggplot2)
myPlot <- ggplot(mpg, aes(displ, hwy)) + 
    geom_point() + 
    facet_grid(class ~ .)

# add annotation
myPlot +
  annotate("rect", xmin = 3, xmax = 4, ymin = -Inf, ymax = Inf, fill = "green", alpha = 1/5)

Что у меня так далеко:

What I have so far

Я хотел бы нарисовать 1 большой прямоугольник, который охватывает грани фасета, вот так:

Messy paint edit of what I want

Есть ли способ сделать это с помощью встроенного кода ggplot2 или с помощью ggforce, или мне нужно возиться с grid? Мой идеальный вариант использования по-прежнему позволял бы мне иметь myPlot в качестве объекта ggplot, поэтому до этой точки я избегал любых сложных вещей с сеткой.

1 Ответ

0 голосов
/ 29 июня 2018

Подход, использующий функции grid для редактирования plot.

Легко нарисовать прямоугольник в окне просмотра grid. Можно ли построить grid область просмотра, которая будет точно перекрывать набор панелей ggplot? Ответ - «Да». Уловка для рисования прямоугольника состоит в том, чтобы получить «родные» координаты оси X из информации ggplot_build в видовой экран сетки.

library(ggplot2)
library(grid)

plot <- ggplot(mpg, aes(displ, hwy)) + 
    geom_point() + 
    facet_grid(class ~ .) 

plot

# Construct a grid.layout that is the same as the ggplot layout
gt = ggplotGrob(plot)
lay = grid.layout(nrow = length(gt$heights), ncol = length(gt$widths),
                  widths = gt$widths, heights = gt$heights)

# Push to this viewport
pushViewport(viewport(layout = lay))

# Within the layout, push to a viewport that spans the plot panels.
pos = gt$layout[grep("panel", gt$layout$name), c("t", "l")]  # Positions of the panels
pushViewport(viewport(layout.pos.col = pos$l, layout.pos.row = min(pos$t):max(pos$t)))

# Get the limits of the ggplot's x-scale, including any expansion.
## For ggplot ver 2.2.1
# x.axis.limits = ggplot_build(plot)$layout$panel_ranges[[1]][["x.range"]]

## For ver 3.0.0
# axis.limits = ggplot_build(plot)$layout$panel_params[[1]]$x.range
# But possibly the following will be more immune to future changes to ggplot
x.axis.limits = summarise_layout(ggplot_build(plot))[1, c('xmin', 'xmax')]


# Set up a data viewport,
# so that the x-axis units are, in effect, "native", 
# but y-axis units are, in effect, "npc".
# And push to the data viewport.
pushViewport(dataViewport(yscale = c(0, 1), 
                          xscale = x.axis.limits))

# Draw the rectangle
grid.rect(x = 3, y = 0,
          width = 1, height = 1,
          just = c("left", "bottom"), default.units = "native",
          gp = gpar(fill = "green", col = "transparent", alpha = .2))

# Back to the root viewport
upViewport(0)

enter image description here

...