如何在R的ggplot2中为柱状图添加多层下方X轴
在ggplot2中为柱状图添加多层X轴的解决方案
我在RStudio中使用ggplot2绘制柱状图时,无法在图表下方添加多层X轴,期望实现多层分类的X轴效果。
当前代码
ggplot(data=relative_trimming_subset, aes(x=Relative_trimming, y=Stage1_time, fill=Trimming)) + geom_bar(stat="identity", position=position_dodge(), show.legend = FALSE) + scale_fill_manual(values = c("#cccccc", "#666666", "#cccccc", "#666666")) + scale_x_discrete(limits = level_order) + theme_bw() + labs(x = "Trimming") + labs(y = "Stage one time (seconds)") + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank()) + theme(panel.border = element_rect(linewidth = 1)) + theme(text = element_text(size = 12), axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0)), axis.line = element_line(colour = 'black'), axis.title = element_text(face="bold"), axis.text.y = element_text(size = 10), axis.text = element_text(colour = 'black'))
尝试过的方法
- 使用
annotate函数添加文本,未成功实现多层X轴 - 尝试
geom_text,同样无法达到预期效果
可复现数据子集
structure(list(ID = c("TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-05MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB", "TF1-07MB"), Sex = c("M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M", "M"), Trimming = c("Untrimmed_full", "Untrimmed_full", "Untrimmed_full", "Untrimmed_full", "Untrimmed_full", "Untrimmed_full", "Untrimmed_full", "Untrimmed_full", "Trimmed_full", "Trimmed_full", "Trimmed_full", "Trimmed_full", "Trimmed_full", "Trimmed_full", "Trimmed_full", "Untrimmed_control", "Untrimmed_control", "Untrimmed_control", "Untrimmed_control", "Untrimmed_control", "Untrimmed_control", "Untrimmed_control", "Untrimmed_control", "Trimmed_control", "Trimmed_control", "Trimmed_control", "Trimmed_control", "Trimmed_control", "Trimmed_control", "Trimmed_control"), Relative_trimming = c("Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Post", "Post", "Post", "Post", "Post", "Post", "Post", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Pre", "Post", "Post", "Post", "Post", "Post", "Post", "Post"), Day = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L), Trial_number = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 1L, 2L, 4L, 5L, 1L, 2L, 5L), Reaction_time = c(40L, 3L, 37L, 5L, 5L, 5L, 5L, 16L, 8L, 13L, 12L, 7L, 5L, 6L, 6L, 3L, 6L, 6L, 6L, 6L, 17L, 13L, 13L, 9L, 14L, 13L, 12L, 5L, 6L, 5L), Stage1_time = c(5L, 5L, 4L, 8L, 5L, 7L, 5L, 8L, 6L, 5L, 7L, 5L, 5L, 8L, 5L, 7L, 7L, 7L, 6L, 8L, 6L, 7L, 7L, 4L, 5L, 5L, 16L, 6L, 8L, 6L), PC1_score = c(-0.080373226, 0.032477537, -0.155069158, 0.1965224, -0.139819473, -0.013115389, -0.069847159, 0.045855081, -0.090945817, -0.118591067, 0.028014289, -0.075510197, -0.02157794, 0.118944384, -0.065654084, 0.102907134, -0.04347041, -0.062195986, 0.028970608, 0.045541099, 0.025417646, 0.074033332, 0.117344171, -0.083718399, -0.029333778, -0.104413751, -0.133641797, -0.020064955, 0.081972399, -0.014783332), S_length = c(3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.274, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254, 3.254), D_length = c(2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 2.028, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839, 1.839), A_length = c(2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.278, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077, 2.077)), class = "data.frame", row.names = c(NA, -30L ))
可行解决方案
方法1:利用facet_wrap实现分组式多层X轴
这种方法适合按大类别分组的场景,通过facet将上层分类作为标签展示在X轴上方:
library(dplyr) library(ggplot2) # 提取数据中的大分组(从ID中分离) relative_trimming_subset$Group <- gsub("-.*", "", relative_trimming_subset$ID) # 计算每组的均值(柱状图建议使用均值而非原始重复数据) plot_data <- relative_trimming_subset %>% group_by(Group, Relative_trimming, Trimming) %>% summarise(Stage1_time_mean = mean(Stage1_time), .groups = "drop") # 定义X轴顺序 level_order <- c("Pre", "Post") # 绘图 ggplot(plot_data, aes(x=Relative_trimming, y=Stage1_time_mean, fill=Trimming)) + geom_bar(stat="identity", position=position_dodge(), show.legend = FALSE) + scale_fill_manual(values = c("#cccccc", "#666666", "#cccccc", "#666666")) + scale_x_discrete(limits = level_order) + # 用facet实现上层X轴 facet_wrap(~Group, scales = "free_x", strip.position = "bottom") + theme_bw() + labs(y = "Stage one time (seconds)") + theme( strip.background = element_rect(fill = "white", color = "black"), strip.text = element_text(face = "bold"), axis.title.x=element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_rect(linewidth = 1), text = element_text(size = 12), axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0), face = "bold"), axis.line = element_line(colour = 'black'), axis.text.y = element_text(size = 10, color = "black"), axis.text.x = element_text(color = "black"), # 消除分组间的间距,让布局更紧凑 panel.spacing.x = unit(0, "mm") )
方法2:手动添加多层轴标签(自定义坐标)
如果不想使用facet,可以手动计算坐标添加文本和分割线,实现自由布局的多层X轴:
library(dplyr) library(ggplot2) # 计算均值数据 plot_data <- relative_trimming_subset %>% group_by(Relative_trimming, Trimming, ID) %>% summarise(Stage1_time_mean = mean(Stage1_time), .groups = "drop") # 定义各层标签的坐标 x_group_pos <- c(1.25, 3.25) # 上层分组标签的中心位置 group_labels <- unique(plot_data$ID) subgroup_labels <- rep(c("Pre", "Post"), 2) # 绘图 ggplot(plot_data, aes(x=interaction(ID, Relative_trimming), y=Stage1_time_mean, fill=Trimming)) + geom_bar(stat="identity", position=position_dodge(), show.legend = FALSE) + scale_fill_manual(values = c("#cccccc", "#666666", "#cccccc", "#666666")) + scale_x_discrete(labels = subgroup_labels) + theme_bw() + labs(y = "Stage one time (seconds)") + theme( axis.title.x=element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), panel.border = element_rect(linewidth = 1), text = element_text(size = 12), axis.title.y = element_text(margin = margin(t = 0, r = 10, b = 0, l = 0), face = "bold"), axis.line = element_line(colour = 'black'), axis.text.y = element_text(size = 10, color = "black"), axis.text.x = element_text(color = "black") ) + # 添加上层分组标签 annotate("text", x = x_group_pos, y = -0.5, label = group_labels, fontface = "bold") + # 添加分组分割线 annotate("segment", x = c(0.5, 2.5), xend = c(2.5, 4.5), y = -0.3, yend = -0.3, color = "black")
内容的提问来源于stack exchange,提问作者cookies5098
相关产品推荐
相关产品推荐

