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

如何实现geom_bar按validated_2填充、按count分面并添加计数?

解决方案:同时实现分组填充、计数分面与大数据适配

原始数据

structure(list(validated_1 = c("sombra", "sombra", "sombra", 
"sombra", "sombra", "sombra", "sombra", "sombra", "sombra", "sombra", 
"coscinodiscus", "sombra", "coscinodiscus", "coscinodiscus", 
"sombra", "coscinodiscus", "sombra", "coscinodiscus", "sombra", 
"coscinodiscus", "coscinodiscus", "detritos", "detritos", "coscinodiscus", 
"appendicularia", "detritos", "coscinodiscus", "coscinodiscus", 
"detritos", "coscinodiscus", "langanho", "detritos", "copepodo", 
"langanho", "copepodo", "langanho", "langanho", "coscinodiscus", 
"coscinodiscus", "coscinodiscus"), validated_2 = c("sombra", 
"sombra", "sombra", "sombra", "sombra", "sombra", "sombra", "sombra", 
"sombra", "sombra", "coscinodiscus", "sombra", "coscinodiscus", 
"coscinodiscus", "sombra", "coscinodiscus", "sombra", "coscinodiscus", 
"sombra", "coscinodiscus", "coscinodiscus", "detritos", "detritos", 
"coscinodiscus", "zooplâncton", "detritos", "coscinodiscus", 
"coscinodiscus", "detritos", "coscinodiscus", "langanho", "detritos", 
"zooplâncton", "langanho", "zooplâncton", "langanho", "langanho", 
"coscinodiscus", "coscinodiscus", "coscinodiscus")), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -40L))

现有处理方式的不足

已尝试两种方式,但均无法满足全部需求:

  • 方式1:支持按计数分面并添加总计数标签,但无法用validated_2变量填充条形
df %>% 
  group_by(validated_1) %>% 
  summarise(count = n()) %>%
  arrange(desc(count)) %>% 
  mutate(groups = c(rep("high N", 2), rep("lower N", 4))) %>% 
  ggplot(aes(x = reorder(validated_1, -count), y = count)) +
  geom_bar(stat = 'identity') +
  facet_wrap(~ groups, nrow = 2, scales = "free") +
  geom_text(aes(label = count), vjust = -0.5, size = 3)
  • 方式2:支持用validated_2填充条形,但无法按计数分面、添加计数标签,且千万行级大数据集下运行速度极慢
df %>%
  ggplot(aes(x = fct_infreq(validated_1), fill = validated_2)) +
  geom_bar()

最终解决方案

核心思路是先对数据进行多层聚合统计,压缩数据量以适配大数据集,再基于聚合后的数据集实现所有需求:

library(tidyverse)

# 1. 多层聚合统计:先按两级标签分组计数,再计算每个一级标签的总计数
agg_df <- df %>%
  group_by(validated_1, validated_2) %>%
  summarise(sub_count = n(), .groups = "drop_last") %>%
  mutate(total_count = sum(sub_count)) %>%
  ungroup() %>%
  # 2. 按总计数排序,分配分面组并转为有序因子
  arrange(desc(total_count)) %>%
  mutate(
    validated_1 = fct_inorder(validated_1),  # 保留总计数从高到低的顺序
    groups = case_when(
      row_number() %in% 1:2 ~ "high N",  # 前2个为高计数组
      TRUE ~ "lower N"                    # 其余为低计数组
    )
  )

# 3. 绘制堆叠条形图:包含填充、分面、双计数标签
agg_df %>%
  ggplot(aes(x = validated_1, y = sub_count, fill = validated_2)) +
  geom_col(position = "stack") +
  # 添加子类别计数标签(位于堆叠条形中间)
  geom_text(aes(label = sub_count), position = position_stack(vjust = 0.5), size = 3) +
  # 添加一级标签总计数标签(位于条形顶部)
  geom_text(
    data = . %>% distinct(validated_1, total_count, groups),
    aes(y = total_count, label = total_count, fill = NULL),
    vjust = -0.5, size = 3.5
  ) +
  facet_wrap(~ groups, nrow = 2, scales = "free") +
  labs(x = "Validated 1", y = "Count", fill = "Validated 2") +
  theme_bw()

方案细节说明

  1. 大数据适配:通过提前聚合统计,将千万行原始数据压缩为validated_1与validated_2的组合级别数据,避免ggplot直接处理海量原始数据,大幅提升运行速度。
  2. 条形填充:使用fill = validated_2配合geom_col(position = "stack")实现堆叠条形的分组填充效果。
  3. 按计数分面:先按总计数排序,通过case_when为每个validated_1分配分面组,再用facet_wrap实现分面展示。
  4. 计数标签:
    • 子类别计数:利用position_stack将标签精准放在每个堆叠条形的中间位置;
    • 总计数:提取每个validated_1的总计数数据,将标签放在条形顶部,避免重复绘制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:15:39