I am having trouble understanding how grobs are being placed into the plotting area. Here's an example of what I mean. Let's assume I have the following plot.
library(tidyverse)
p <- mpg %>%
ggplot(aes(year)) +
geom_bar()
p

I understand that I can get a list of grobs from that and plot it like so.
l <- ggplotGrob(p)
grid::grid.newpage()
grid::grid.draw(l)
From the structure of list l I also understand that the rectangles are drawn as rectGrobs. I found these in.
grobs <- l$grobs[[6]]
rect_grobs <- grobs$children[[3]]
But if I want to plot at least one rectangle using the data straight from rect_grobs, nothing happens. This is independent of whether I create a new canvas with grid::grid.newpage() or not.
# This draws nothing
grid::grid.draw(
grid::rectGrob(
x = rect_grobs$x[1],
y = rect_grobs$y[1],
height = rect_grobs$height[1],
width = rect_grobs$width[1],
just = rect_grobs$just[1],
)
)
Yet if I plug in the values from rect_grobs by hand, then a rectangle is drawn in the wrong position. I suspect that this is related to viewports but I tried looking in l, grobs and rect_grobs but I found no clue what viewport so set. Wherever I look, there is only vp = NULL.
# This draws in wrong position
grid::grid.draw(
grid::rectGrob(
x = 0.0455,
y = 0.955,
width = 0.431,
height = 0.909,
just = 'left'
)
)

So, my questions are
- Why does the code not draw a rectangle if I take the values straight from the
rect_grobslist? - How do I get the rectangle into the correct position if I manually add it?
The reason why
rect_grobsdoesn't draw is indeed that it has no viewport. If a grob has no viewport set, it will inherit from its parent, but since you have plucked it out of agTable, it has no parent. This is easy to rectify by giving it a default viewport:As long as we specify the correct
just, we get the rectangle in the same place:However, this is not the position the rectangle would be in a ggplot. That's because in
ggplotthe panel has its own viewport. To draw the rectangle in this context, we need to navigate to the correct viewport before callinggrid.draw