ggplot2 facet_grid不遵循因子水平:预因子化失效原因及解决方法问询
问题描述
我用ggplot2的facet_grid()绘制3个分面图,默认分面和图例都是字母顺序。为调整顺序,我对相关变量做了因子化,也确认设置了目标水平,但分面还是保持字母顺序,只有图例的样本顺序和颜色分配因为因子化改变了。
我找到很多在绘图代码里加因子设置的方案,但想提前对数据做因子化,尽量简化绘图代码。
请问为什么我的因子化方法对分面排列不起作用?有没有简单的方法能在绘图前设置因子水平,让facet_grid()遵循这个设置?
复现代码
library(tidyverse) Sample_Table <- data.frame( Sample=c(1:9), Group=c("B", "B", "B", "A", "A", "A", "C", "C", "C")) data <- data.frame( Position=c(rep(1:5000,times=3)), Signal=c(rep(0,times=2000), rep(25,times=1000), rep(0,times=2000), rep(0,times=2000), rep(50,times=1000), rep(0,times=2000), rep(0,times=2000), rep(75,times=1000), rep(0,times=2000)), Group=c(rep("A", times=5000), rep("B", times=5000), rep("C", times=5000)) ) data_factor <- data %>% dplyr::mutate(Group = factor(Group, levels=c(paste0(unique(Sample_Table$Group))))) colorscale <- c("#ffe119", "#f58231", "#9A6324") Plot <- ggplot(data) + geom_line(aes(x=Position, y=Signal, col=Group), linewidth=.4) + scale_color_manual(values=c(colorscale)) + facet_grid(paste0(Group)~.) + theme_bw() + theme(axis.text.x = element_blank()) + theme( axis.title.x = element_text(margin=margin(t=30)), legend.title = element_text(colour = "#333333", size=12), legend.text = element_text(colour = "#333333", size=12) ) + guides(fill = "none") Plot_Factored <- ggplot(data_factor) + geom_line(aes(x=Position, y=Signal, col=Group), linewidth=.4) + scale_color_manual(values=c(colorscale)) + facet_grid(paste0(Group)~.) + theme_bw() + theme(axis.text.x = element_blank()) + theme( axis.title.x = element_text(margin=margin(t=30)), legend.title = element_text(colour = "#333333", size=12), legend.text = element_text(colour = "#333333", size=12) ) + guides(fill = "none")
效果对比
原始绘图(未因子化数据)

因子化数据但分面未生效的绘图

原因分析
问题核心出在**facet_grid(paste0(Group)~.)**这行代码:你用paste0()把已经因子化的Group变量强制转回了字符串类型,ggplot处理字符串时会默认按字母顺序排序分面;而图例使用的是aes()里的因子化Group,所以图例顺序和颜色能正常遵循因子设置。
解决方案
直接在facet_grid()中使用因子化后的Group变量,不要用paste0()做转换:
修正后的绘图代码
Plot_Factored <- ggplot(data_factor) + geom_line(aes(x=Position, y=Signal, col=Group), linewidth=.4) + scale_color_manual(values=colorscale) + facet_grid(Group~.) + # 移除paste0(),直接用因子变量 theme_bw() + theme(axis.text.x = element_blank(), axis.title.x = element_text(margin=margin(t=30)), legend.title = element_text(colour = "#333333", size=12), legend.text = element_text(colour = "#333333", size=12)) + guides(fill = "none")
简化因子化代码
另外,你设置因子水平的代码可以简化,unique(Sample_Table$Group)本身就是字符向量,无需paste0():
data_factor <- data %>% mutate(Group = factor(Group, levels = unique(Sample_Table$Group)))
这样修改后,分面就会严格遵循你提前设置的因子水平顺序排列,同时保持绘图代码简洁。
内容的提问来源于stack exchange,提问作者JVGen
相关产品推荐
相关产品推荐

