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
相关产品推荐
相关产品推荐

