如何在 ggplot2 facet_grid 右侧显示限值名称和值?
数据阿明
可以。facet_grid() 没有参数可将每个分面的 almin、almax 值显示为额外的列条带。可以在最右侧分面内添加文字标签,并扩展 x 轴范围,为标签留出空间。扩展绘图区域后,geom_hline() 也会延伸到标签区,因此示例改用 geom_segment(),将限值线限制在数据区域内。
示例沿用问题中的 df 和 select_bmk,并假设最右侧的 site 是因子水平中的最后一个值(示例中为 C):
library(ggplot2)
library(dplyr)
select_bmk <- "bmk3"
sel <- df |> filter(bmk == select_bmk)
# 标签放在最右侧的 site 分面
last_site <- tail(levels(droplevels(sel$site)), 1)
x_range <- range(sel$x, na.rm = TRUE)
x_span <- diff(x_range)
# 为标签位置和标签文字预留右侧空间
x_label <- x_range[2] + 0.05 * x_span
x_right <- x_range[2] + 0.8 * x_span
# 每个 qc、site 组合保留一组限值,用于绘制线段
limit_lines <- sel |>
distinct(qc, site, almin, almax)
# 仅在最右侧 site 分面生成限值文字
limit_labels <- limit_lines |>
filter(site == last_site) |>
transmute(
qc, site,
x = x_label,
y = almin,
label = sprintf("almin (%.2f)", almin)
) |>
bind_rows(
limit_lines |>
filter(site == last_site) |>
transmute(
qc, site,
x = x_label,
y = almax,
label = sprintf("almax (%.2f)", almax)
)
)
sel |>
ggplot(aes(x = x, y = y)) +
geom_point() +
geom_segment(
data = limit_lines,
aes(x = x_range[1], xend = x_range[2], y = almin, yend = almin),
inherit.aes = FALSE,
linetype = "longdash",
colour = "red3"
) +
geom_segment(
data = limit_lines,
aes(x = x_range[1], xend = x_range[2], y = almax, yend = almax),
inherit.aes = FALSE,
linetype = "longdash",
colour = "red3"
) +
geom_text(
data = limit_labels,
aes(x = x, y = y, label = label),
inherit.aes = FALSE,
hjust = 0,
size = 3
) +
facet_grid(qc ~ site, scales = "free_y") +
coord_cartesian(xlim = c(x_range[1], x_right))
limit_labels 中包含 qc 和 site,facet_grid() 会据此将文字放到对应的行和列。筛选 last_site 后,标签只会显示在最右侧列。coord_cartesian() 扩大显示范围时会保留范围外的数据;线段仍以原数据的 x 范围为终点,因此不会穿过标签区。
如果实际数据中的限值名称分布在多列,可以先将这些列整理成长格式,再用同样的方法生成标签数据。这里的代码使用问题中提供的 almin、almax 两列。标签间距和 x_right 可根据图形和标签长度调整。如果多个限值的 y 值接近,文字可能重叠,此时需要进一步调整标签位置或字号。
备注:内容仅供参考。
