在R语言ggplot中同时按频率与字母顺序重排条形图
解决ggplot条形图按频率降序+同频率正字母排序的问题
需求说明
需要实现条形图的双重排序规则:
- 优先按频率(Abs_fam.Freq)降序排列
- 频率相同的类别,按名称(Abs_fam.Var1)正字母顺序排列
当前使用reorder(Abs_fam.Var1, Abs_fam.Freq)仅能实现频率排序,但同频率类别会呈现逆字母顺序,不符合期望。
当前输出与期望输出
当前输出(同频率逆字母):
G - 60 T - 50 C - 40 B - 40 A - 40
期望输出(同频率正字母):
G - 60 T - 50 A - 40 B - 40 C - 40
示例数据与现有代码
示例数据
fam_sub <- structure( list( Abs_fam.Var1 = c( "Apio", "Myria", "Xyla", "Rhyti", "Hypo", "Phaci" ), Abs_fam.Freq = c(1L, 1L, 1L, 2L, 8L, 53L) ), row.names = c(NA,-6L), groups = structure( list( Abs_fam.Freq = c(1L, 2L, 8L, 53L), .rows = structure( list(1:3, 4L, 5L, 6L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list") ) ), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,-4L), .drop = TRUE ), class = c("grouped_df", "tbl_df", "tbl", "data.frame"))
现有绘图代码
library(ggplot2) ggplot(fam_sub, aes(x = reorder(Abs_fam.Var1, Abs_fam.Freq), y = Abs_fam.Freq)) + geom_col(fill = "#559355") + coord_flip() + theme_minimal()
解决方案
推荐先手动处理数据的因子水平,再绘图,逻辑更清晰易维护:
library(ggplot2) library(dplyr) # 1. 取消数据分组,按规则排序后定义因子水平 fam_sub_sorted <- fam_sub %>% ungroup() %>% # 先按频率降序,再按名称正字母排序 arrange(desc(Abs_fam.Freq), Abs_fam.Var1) %>% # 将名称转为因子,水平顺序为排序后的结果 mutate(Abs_fam.Var1 = factor(Abs_fam.Var1, levels = Abs_fam.Var1)) # 2. 绘图 ggplot(fam_sub_sorted, aes(x = Abs_fam.Var1, y = Abs_fam.Freq)) + geom_col(fill = "#559355") + coord_flip() + theme_minimal()
如果不想提前处理数据,也可以直接在aes()中用自定义规则的reorder():
library(ggplot2) library(dplyr) ggplot(fam_sub %>% ungroup(), aes(x = reorder(Abs_fam.Var1, # 先按负频率实现降序,再按名称正序微调排序值 -Abs_fam.Freq + as.integer(factor(Abs_fam.Var1))/1000), y = Abs_fam.Freq)) + geom_col(fill = "#559355") + coord_flip() + theme_minimal()
原理说明
默认reorder()函数在排序变量值相同时,会保留原因子水平的逆序排列。通过手动定义因子水平,或在排序值中加入基于名称字母顺序的微小偏移,就能让同频率类别按正字母顺序排列。
内容的提问来源于stack exchange,提问作者rousou
相关产品推荐
相关产品推荐

