You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot分面图的每个分面中绘制不同的grob?

解决ggplot分面中geom_grob重复显示最后一个grob的问题

问题描述

在ggplot分面图中,尝试用ggpmisc::geom_grob为每个分面添加不同的grob(如汇总统计表格),但所有分面仅显示最后一个grob。复现代码如下:

library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#>     filter, lag
#> The following objects are masked from 'package:base':
#>
#>     intersect, setdiff, setequal, union
library(ggplot2)
library(gridExtra)
#>
#> Attaching package: 'gridExtra'
#> The following object is masked from 'package:dplyr':
#>
#>     combine
library(ggpmisc)
#> Loading required package: ggpp
#>
#> Attaching package: 'ggpp'
#> The following object is masked from 'package:ggplot2':
#>
#>     annotate

p1 <- iris |>
  ggplot(aes(x=Petal.Length)) +
  geom_density() +
  facet_wrap(vars(Species))

stats <- iris |>
  group_by(Species) |>
  summarise(Mean = round(mean(Petal.Length), 3),
            SD = round(sd(Petal.Length), 3))

g1 <- filter(stats, Species == "setosa") |> tableGrob(rows=NULL)
g2 <- filter(stats, Species == "versicolor") |> tableGrob(rows=NULL)
g3 <- filter(stats, Species == "virginica") |> tableGrob(rows=NULL)

grobs <- tibble(x=4, y=2, grobs = list(g1,g2,g3))

p1 +
  geom_grob(data=grobs, aes(x=x, y=y, label=grobs))

问题效果图:
所有分面显示最后一个grob的错误效果

原因分析

当前的grobs数据框未关联分面变量Species,ggplot在分面渲染时无法将每个grob与对应分面匹配,最终所有分面都调用了列表中的最后一个grob元素。

解决方案

在grobs数据框中加入分面变量Species,让每个grob与对应的分面标签绑定,确保geom_grob能根据分面变量匹配正确的grob。

修改后的代码

library(dplyr)
library(ggplot2)
library(gridExtra)
library(ggpmisc)

p1 <- iris |>
  ggplot(aes(x=Petal.Length)) +
  geom_density() +
  facet_wrap(vars(Species))

stats <- iris |>
  group_by(Species) |>
  summarise(Mean = round(mean(Petal.Length), 3),
            SD = round(sd(Petal.Length), 3))

g1 <- filter(stats, Species == "setosa") |> tableGrob(rows=NULL)
g2 <- filter(stats, Species == "versicolor") |> tableGrob(rows=NULL)
g3 <- filter(stats, Species == "virginica") |> tableGrob(rows=NULL)

# 加入Species变量,关联每个grob到对应分面
grobs <- tibble(
  Species = c("setosa", "versicolor", "virginica"),
  x = 4, 
  y = 2, 
  grobs = list(g1,g2,g3)
)

p1 +
  geom_grob(data=grobs, aes(x=x, y=y, label=grobs))

更简洁的批量生成方式

如果分面数量较多,可使用purrr::map批量生成grob并自动关联分面变量:

library(dplyr)
library(ggplot2)
library(gridExtra)
library(ggpmisc)
library(purrr)

p1 <- iris |>
  ggplot(aes(x=Petal.Length)) +
  geom_density() +
  facet_wrap(vars(Species))

stats <- iris |>
  group_by(Species) |>
  summarise(Mean = round(mean(Petal.Length), 3),
            SD = round(sd(Petal.Length), 3))

# 批量生成grob并绑定分面变量
grobs <- stats |>
  mutate(
    grobs = map(rowwise(), ~tableGrob(.x[, c("Mean", "SD")], rows = NULL)),
    x = 4,
    y = 2
  )

p1 +
  geom_grob(data = grobs, aes(x = x, y = y, label = grobs))

修改后每个分面将显示对应物种的统计表格grob。

内容的提问来源于stack exchange,提问作者Claudio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:55:20