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

ggplot中自定义X轴标签颜色未按subset分组预期生效的问题求助

ggplot中自定义X轴标签颜色未按subset分组预期生效的问题求助

我太懂你这种卡了两小时越试越懵的感觉!先帮你揪出问题所在,再给你直接能用的解决方案~

首先梳理你的需求:你希望Initial分组下的两个X轴标签(Training和Validation)都显示grey50,Processed分组下的两个标签都显示midnightblue,但现在只有Validation标签的颜色符合预期,Training的颜色乱了,对吧?

问题根源

问题出在X轴标签的实际显示顺序,和你生成颜色向量a时用的原始数据顺序不匹配:

  • 你的df_TP里categ的顺序是:initial_t_tp → processed_t_tp → initial_v_tp → processed_v_tp,所以生成的a颜色顺序是grey50→midnightblue→grey50→midnightblue
  • 但用facet_grid(. ~ subset, scales="free_x")后,ggplot会把X轴标签按分面分组排列,实际显示顺序是:initial_t_tp(Initial-Training)→ initial_v_tp(Initial-Validation)→ processed_t_tp(Processed-Training)→ processed_v_tp(Processed-Validation)
  • 这就导致你给的颜色向量和实际标签的对应关系完全错位,最终出现颜色不符合预期的情况。

解决方案

你只需要生成一个和实际X轴标签顺序完全匹配的颜色向量就行,有两种简单的方法:

方法一:按分面顺序排序数据后生成颜色向量

先把数据按subset排序,确保顺序和分面后X轴的显示顺序一致,再生成颜色:

library(dplyr) # 需要加载dplyr包
# 按subset排序,先initial再processed
sorted_df <- df_TP %>% arrange(subset)
# 根据subset生成对应颜色
correct_cols <- ifelse(sorted_df$subset == "initial", "grey50", "midnightblue")

然后把theme里的axis.text.x部分改成:

axis.text.x = ggtext::element_markdown(
  size = 25, vjust = 3, colour = correct_cols
),

方法二:直接手动定义正确的颜色向量

因为你知道X轴标签的实际顺序,也可以直接写死颜色向量,更直接:

# 顺序对应:Initial-Training, Initial-Validation, Processed-Training, Processed-Validation
correct_cols <- c("grey50", "grey50", "midnightblue", "midnightblue")

同样替换theme里的colour = correct_cols即可。

完整修正后的代码

把上面的方法整合到你的代码里,完整代码如下:

library(ggplot2)
library(ggtext)
library(dplyr) # 方法一需要用到

df_TP <- data.frame(
  categ = c("initial_t_tp", "processed_t_tp", "initial_v_tp", "processed_v_tp"),
  group = rep("TP", 4),
  absolute = c(86, 85, 21, 21),
  percentage = c(84.16, 84.16, 84.00, 84.00),
  col = c(0, 1, 0, 1),
  subset = c("initial", "processed", "initial", "processed")
)

labels_tp <- c(
  "initial_t_tp" = "Training",
  "initial_v_tp" = "Validation",
  "processed_v_tp" = "Validation",
  "processed_t_tp" = "Training"
)

# 方法一:排序后生成颜色向量
sorted_df <- df_TP %>% arrange(subset)
correct_cols <- ifelse(sorted_df$subset == "initial", "grey50", "midnightblue")

# 或者用方法二:手动定义
# correct_cols <- c("grey50", "grey50", "midnightblue", "midnightblue")

# Create the bar plot with separation
ggplot(
  df_TP,
  aes(x = categ, y = absolute, fill = subset)
) +
  geom_col(aes(fill = subset)) +
  labs(x = NULL, y = "# detected events") +
  scale_fill_manual(
    values = c("initial" = "grey50", "processed" = "midnightblue")
  ) +
  theme_minimal() +
  theme(
    axis.title.y = element_text(
      size = 30, color = "grey50",
      vjust = 2, hjust = 0.95),
    axis.text.y = element_text(size = 25, colour = "grey50"),
    axis.text.x = ggtext::element_markdown(
      size = 25, vjust = 3, colour = correct_cols
    ),
    strip.text = element_blank(),
    panel.grid.major.y = element_line(size = 0.5, color = "grey85"),
    panel.grid.major.x = element_blank(),
    panel.grid.minor = element_blank(),
    legend.position = "none",
    plot.margin = margin(l = 20, 0, 0, 0),
    aspect.ratio = 1/0.9
  ) +
  coord_cartesian(
    ylim = c(0, 90), clip = 'off'
  ) +
  facet_grid(
    . ~ subset, scales = "free_x", switch = "x",
  ) +
  scale_y_continuous(
    limits = c(0, 90), breaks = seq(0, 90, by = 30)
  ) +
  scale_x_discrete(labels = labels_tp)

这样修改后,Initial分组下的两个标签都会是grey50,Processed分组下的两个都会是midnightblue,完全符合你的需求啦!

备注:内容来源于stack exchange,提问作者Barbara Perez de Araújo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 09:08:04