ggplot2 geom_rect() in R: Draw Rectangles
The geom_rect() function in ggplot2 draws rectangles from explicit xmin, xmax, ymin, ymax coordinates. Useful for highlighting regions, time-period shading, or custom annotations.
ggplot(df, aes(xmin = x1, xmax = x2, ymin = y1, ymax = y2)) + geom_rect() geom_rect(aes(...), fill = "yellow", alpha = 0.3) geom_tile(...) # different: x, y, width, height annotate("rect", xmin = ..., ...) # one-off rectangle
Need explanation? Read on for examples and pitfalls.
What geom_rect() does in one sentence
geom_rect() draws rectangles defined by xmin, xmax, ymin, ymax aesthetics. Each row produces ONE rectangle.
Syntax
geom_rect(mapping = NULL, data = NULL, fill = "grey50", alpha = 1, ...). Requires aes(xmin, xmax, ymin, ymax).
inherit.aes = FALSE when geom_rect's aesthetics differ from the main plot. Otherwise ggplot tries to apply parent aesthetics.Five common patterns
1. Highlight time period
2. Multiple rectangles
3. Background grid cells
4. With borders
5. annotate alternative
annotate("rect", ...) is cleaner than geom_rect() because it doesn't require a data frame. For data-driven rectangles (multiple regions), use geom_rect.geom_rect() vs geom_tile() vs annotate()
| Function | Spec | Best for |
|---|---|---|
geom_rect() |
xmin/xmax/ymin/ymax | Data-driven rectangles |
geom_tile() |
x, y, width, height | Heatmaps |
annotate("rect", ...) |
Same as geom_rect | One-off rectangle |
A practical workflow
Use geom_rect for time-period shading on time-series plots.
Recession bands behind a time-series line.
Common pitfalls
Pitfall 1: forgetting inherit.aes = FALSE. Without it, ggplot tries to apply the main plot's aesthetics to geom_rect, which may not have x/y mapped.
Pitfall 2: y range for full-height bands. Use ymin = -Inf, ymax = Inf for full-height shading.
geom_rect() requires all four corner aesthetics. Missing any errors at runtime.Try it yourself
Try it: Add a yellow rectangle highlighting cars with 4-6 cyl in mtcars wt-mpg scatter. Save to ex_plot.
Click to reveal solution
Explanation: annotate is cleaner for a one-off rectangle. Yellow band highlights light, efficient cars.
Related ggplot2 functions
After mastering geom_rect, look at:
geom_tile(): heatmap tilesannotate("rect", ...): one-off rectanglegeom_polygon(): irregular shapesgeom_ribbon(): between-curves areageom_vline()/geom_hline(): reference lines
FAQ
What does geom_rect do in ggplot2?
geom_rect() draws rectangles from xmin/xmax/ymin/ymax aesthetics. Each row produces one rectangle.
What is the difference between geom_rect and geom_tile?
geom_rect uses corner coordinates (xmin/xmax/ymin/ymax). geom_tile uses center + width/height. geom_tile is more common for heatmaps.
How do I add a single rectangle annotation?
Use annotate("rect", xmin = ..., ...) instead of geom_rect. No data frame needed.
How do I make full-height bands?
Pass ymin = -Inf, ymax = Inf. This extends the rectangle to the plot's full y range.
Why does geom_rect error in my plot?
Often because the parent plot has different aesthetics. Pass inherit.aes = FALSE to make geom_rect ignore them.