ggplot2 添加注释跨越小平面边缘
ggplot2 add annotation spanning facet edges
我想在 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)
我目前拥有的:
我想像这样绘制 1 个跨越小平面边缘的大矩形:
有没有办法使用内置的 ggplot2
代码或 ggforce
来做到这一点,或者我是否必须乱用 grid
?我理想的用例仍然允许我将 myPlot
作为 ggplot 对象,这就是为什么我一直避免使用任何复杂的网格内容。
一种使用 grid
函数来编辑 plot
的方法。
在 grid
视口中绘制矩形很容易。是否可以构建一个 grid
视口来准确覆盖一组 ggplot 面板?答案是"Yes"。绘制矩形的技巧是将 ggplot_build
信息中的 x 轴 "native" 坐标获取到网格视口中。
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)
我想在 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)
我目前拥有的:
我想像这样绘制 1 个跨越小平面边缘的大矩形:
有没有办法使用内置的 ggplot2
代码或 ggforce
来做到这一点,或者我是否必须乱用 grid
?我理想的用例仍然允许我将 myPlot
作为 ggplot 对象,这就是为什么我一直避免使用任何复杂的网格内容。
一种使用 grid
函数来编辑 plot
的方法。
在 grid
视口中绘制矩形很容易。是否可以构建一个 grid
视口来准确覆盖一组 ggplot 面板?答案是"Yes"。绘制矩形的技巧是将 ggplot_build
信息中的 x 轴 "native" 坐标获取到网格视口中。
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)