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

如何为基于3种X轴值的12个geom_bar分别设置自定义颜色?

问题描述

我用给定数据生成了堆叠柱状图(代码如下),当前图表里有12个堆叠的geom_bar,原本是按speclib的两个因子分组上色,现在想手动给这12个柱子的每个堆叠分段都设置独立颜色,预期效果是每个分段都有专属的自定义色彩(参考样图中每个堆叠部分颜色各不相同,没有统一的分组配色)。

原始生成代码

ggplot(q, aes(x = digest_method, y = diff, color = forcats::fct_rev(speclib), fill = forcats::fct_rev(speclib))) + 
  geom_bar(stat = "identity", position = "stack") + 
  geom_text(aes(y = protein_total, label = protein_total), vjust = rep(c(1.5, -0.5), 6), show.legend = FALSE) + 
  facet_wrap(~ frak, nrow = 1)

数据

q <- structure(list(digest_method = c("Direct", "Direct", "Direct", "Direct", "In solution", "In solution", "In solution", "In solution", "PAC", "PAC", "PAC", "PAC"), protein_total = c(780L, 1173L, 948L, 1526L, 891L, 1444L, 1442L, 1880L, 947L, 1704L, 1598L, 2433L), speclib = c("No", "SpecLib", "No", "SpecLib", "No", "SpecLib", "No", "SpecLib", "No", "SpecLib", "No", "SpecLib"), frak = structure(c(1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), levels = c("Raw", "20K Vesicles", "120K Vesicles", "Vesicles depleted"), class = "factor"), diff = c(780L, 393L, 948L, 578L, 891L, 553L, 1442L, 438L, 947L, 757L, 1598L, 835L)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -12L), groups = structure(list(frak = structure(c(1L, 1L, 1L, 2L, 2L, 2L), levels = c("Raw", "20K Vesicles", "120K Vesicles", "Vesicles depleted"), class = "factor"), digest_method = c("Direct", "In solution", "PAC", "Direct", "In solution", "PAC"), .rows = structure(list(1:2, 5:6, 9:10, 3:4, 7:8, 11:12), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))
解决方案

要实现每个堆叠分段单独设色,关键是给每个分段创建唯一标识,再用这个标识映射颜色,手动指定对应色彩。

第一步:给每个分段加唯一ID

给数据框q新增一列segment_id,每行对应一个唯一的堆叠分段(正好12个):

q <- q %>% mutate(segment_id = row_number())

第二步:准备自定义颜色向量

准备12个颜色,数量和分段数一致,你可以替换成自己想要的色值:

custom_colors <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7", "#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442")

第三步:修改ggplot代码

把fill和color的映射从speclib改成segment_id,再用scale_fill_manual和scale_color_manual绑定自定义颜色:

ggplot(q, aes(x = digest_method, y = diff, color = factor(segment_id), fill = factor(segment_id))) + 
  geom_bar(stat = "identity", position = "stack") + 
  geom_text(aes(y = protein_total, label = protein_total), vjust = rep(c(1.5, -0.5), 6), show.legend = FALSE) + 
  facet_wrap(~ frak, nrow = 1) +
  scale_fill_manual(values = custom_colors) +
  scale_color_manual(values = custom_colors) +
  guides(fill = "none", color = "none") # 不需要图例就保留这行,要的话删掉

补充说明

  • segment_id的顺序和数据框行顺序一致,所以颜色向量的顺序要对应,确保每个分段颜色匹配正确
  • 如果需要保留图例,去掉最后一行的guides代码即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:42:02