R与ggplot中含数字字符串排序异常:如何实现正确数值顺序?
解决含数字字符串的排序问题
在ggplot中,字符型分类变量默认按字典序排序,因此会出现asq_1, asq_10, asq_11...asq_2的混乱顺序。要让含数字的字符串按数值顺序展示,核心是把变量转换成有序因子,按数字部分的大小指定排序规则。
修改后的完整代码
library(tidyverse) df = data.frame(x = 1:3) for (i in 1:15) { df[ , paste0("asq_", i)] <- c(0,5,10) } df %>% pivot_longer(-x, names_to = "asq_item", values_to = "response") %>% # 提取字符串中的数字,转换为整数后排序,将asq_item转为有序因子 mutate(asq_item = fct_reorder(asq_item, as.integer(str_extract(asq_item, "\\d+")))) %>% group_by(asq_item, response) %>% summarise(count = n(), .groups = 'drop') %>% group_by(asq_item) %>% mutate(proportion = count / sum(count)) %>% ggplot(aes(x = asq_item, y = proportion, fill = factor(response)))+ geom_bar(stat = "identity", position=position_dodge2(width = 0.9, preserve = "single")) + labs(title = "每个ASQ条目下各分类的占比", x = "ASQ条目", y = "占比", fill = "响应值") + theme_bw()
关键步骤说明
str_extract(asq_item, "\\d+"):从asq_item中提取所有数字字符(比如从asq_12提取"12")as.integer():把提取到的数字字符串转为整数,用于确定排序逻辑fct_reorder(asq_item, ...):将asq_item转换为因子,并按照后面的数值变量排序,这样ggplot的x轴就会按asq_1, asq_2...asq_15的顺序展示。
另一种方法:用gtools::mixedorder指定因子水平
如果你更习惯用gtools包,可以直接把asq_item转为因子,指定水平为mixedorder排序后的结果:
library(gtools) df_processed <- df %>% pivot_longer(-x, names_to = "asq_item", values_to = "response") # 指定因子水平为mixedorder排序后的顺序 df_processed$asq_item <- factor(df_processed$asq_item, levels = df_processed$asq_item[mixedorder(df_processed$asq_item)]) # 后续的统计和绘图代码不变 df_processed %>% group_by(asq_item, response) %>% summarise(count = n(), .groups = 'drop') %>% group_by(asq_item) %>% mutate(proportion = count / sum(count)) %>% ggplot(aes(x = asq_item, y = proportion, fill = factor(response)))+ geom_bar(stat = "identity", position=position_dodge2(width = 0.9, preserve = "single")) + labs(title = "每个ASQ条目下各分类的占比", x = "ASQ条目", y = "占比", fill = "响应值") + theme_bw()
之前用mixedsort没生效,是因为mixedsort只是对向量排序,但如果asq_item还是字符型,ggplot依然会按字典序处理。必须把它转为因子,手动指定排序后的水平才能生效。
内容的提问来源于stack exchange,提问作者Luis
相关产品推荐
相关产品推荐

