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

如何在ggplot2分面小提琴图中添加分组观测数标注?

给分面小提琴图的每个小提琴添加观测数标注

需求:在分面小提琴图的每个小提琴旁标注绘制该小提琴所用的观测数量,现有未添加标注的示例代码:

library(ggplot2)
library(dplyr)
library(tidyverse)

data("iris")

c <- rep(c('r', 'g', 'b'), 50)
c <- sample(c)
facet_row <- rep(c('row1', 'row2', 'row3', 'row4', 'row5'), 30)
facet_col <- rep(c('col1', 'col2', 'col3'), 50)

iris$facet_rows <- facet_row
iris$facet_cols <- facet_col
iris$color <- c
iris$count <- sample(1:10, size = 150, replace = T)

p <- ggplot(iris, aes(x=Species, y=Petal.Length, fill=color)) + 
  geom_violin(alpha = 0.7, na.rm = T) +
  coord_flip() +
  facet_grid(rows = vars(facet_rows), cols = vars(facet_cols))

print(p)

尝试两种方法均存在问题:

  • 方法一:使用stat_summary自定义函数,仅显示Species分组的总数,无法区分不同color子分组的观测数:
count_data <- function (y){
  df <- data.frame(y = min(y) - 0.2, label = length(y))
  return(df)
}

p <- ggplot(iris, aes(x=Species, y=Petal.Length, fill=color)) + 
  geom_violin(alpha = 0.7, na.rm = T) + stat_summary(fun.data = count_data, geom = "text", aes(group = Species)) +
  coord_flip() +
  facet_grid(rows = vars(facet_rows), cols = vars(facet_cols))

print(p)

问题原因:group = Species参数强制按物种分组统计,忽略了color的子分组维度。

  • 方法二:直接用geom_text添加预计算的count字段,存在两个问题:同组小提琴的标注重叠在同一行、每个观测会重复绘制一次标注:
p <- ggplot(iris, aes(x=Species, y=Petal.Length, fill=color)) + 
  geom_violin(alpha = 0.7, na.rm = T) + geom_text(aes(label=count, y=Petal.Length), nudge_y = -0.1) +
  coord_flip() +
  facet_grid(rows = vars(facet_rows), cols = vars(facet_cols))

print(p)

问题原因:原数据集每行对应一个观测,geom_text会逐行渲染;且未针对color分组调整位置,导致标注重叠。


正确实现方法

核心思路:先按分面维度(facet_rows、facet_cols)、Species、color全维度分组,计算每个小提琴对应的观测数,再用汇总后的数据集添加文本标注,同时通过位置对齐避免重叠。

步骤1:预计算分组观测数

# 按所有分组维度汇总,计算每个小提琴的观测数,同时确定标注的y轴位置
label_data <- iris %>%
  group_by(facet_rows, facet_cols, Species, color) %>%
  summarise(
    n = n(),
    y_pos = min(Petal.Length) - 0.3, # 标注固定在小提琴下方
    .groups = "drop"
  )

步骤2:绘制带标注的小提琴图

p <- ggplot(iris, aes(x=Species, y=Petal.Length, fill=color)) + 
  geom_violin(alpha = 0.7, na.rm = T, position = position_dodge(width = 0.8)) +
  # 添加观测数标注,使用汇总后的数据集,位置与小提琴对齐
  geom_text(
    data = label_data,
    aes(x=Species, y=y_pos, label = paste0("n=", n), group = color),
    position = position_dodge(width = 0.8), # 和小提琴的分组位置匹配
    size = 3
  ) +
  coord_flip() +
  facet_grid(rows = vars(facet_rows), cols = vars(facet_cols))

print(p)

关键说明:

  1. group_by包含所有维度,确保每个小提琴对应唯一的观测数统计结果。
  2. position_dodge(width = 0.8)让标注和小提琴的分组位置完全对齐,避免同组内的标注重叠。
  3. 用y_pos固定标注在小提琴下方,避免标注随观测值波动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 13:27:17