R语言堆叠条形图Y轴类别排序调整求助
调整ggplot2堆叠条形图的Y轴类别顺序(coord_flip后)
问题背景
作为R语言完全新手,已使用ggplot2绘制出堆叠条形图,但通过coord_flip()转换后,Y轴对应原X轴的Scenario类别顺序不符合需求,图表其他部分均符合预期。
当前使用的绘图代码
scenarios_summary_diverging_right_order %>% ggplot(aes(x = Scenario, y = percent_answers, fill = Opinion)) + geom_col() + geom_text(aes(label = percent_answers_label), position = position_stack(vjust = 0.5), color = "white", fontface = "bold") + coord_flip() + scale_x_discrete() + scale_fill_viridis_d(breaks = c("Strongly disagree", "Disagree", "Undecided","Agree", "Strongly agree")) + labs(title = "To what extent do you agree that this is a display of aggressive behaviour?", x = NULL, fill = NULL) + theme_minimal() + theme(axis.text.x = element_blank(), axis.title.x = element_blank(), panel.grid = element_blank(), legend.position = "top")
尝试过的无效代码
scenarios_summary_diverging_right_order %>% mutate(Scenario = fct_reorder(Scenario, Opinion)) %>% ggplot( aes(x=Opinion, y=Scenario)) + geom_bar(stat="identity", fill="#f68060", alpha=.6, width=.4) + coord_flip() + xlab("") + theme_bw()
示例数据
structure(list(Scenario = c("Scenario 1", "Scenario 1", "Scenario 1", "Scenario 1", "Scenario 1", "Scenario 2", "Scenario 2", "Scenario 2", "Scenario 2", "Scenario 2"), Opinion = structure(c(2L, 5L, 1L, 4L, 3L, 2L, 5L, 1L, 4L, 3L), levels = c("Strongly agree", "Agree", "Undecided", "Strongly disagree", "Disagree"), class = "factor"), n_answers = c(25L, 98L, 1L, 20L, 107L, 54L, 63L, 4L, 21L, 105L), percent_answers = c(0.099601593625498, -0.390438247011952, 0.00398406374501992, -0.0796812749003984, 0.426294820717131, 0.218623481781377, -0.255060728744939, 0.0161943319838057, -0.0850202429149798, 0.425101214574899), percent_answers_label = c("10%", "39%", "0%", "8%", "43%", "22%", "26%", "2%", "9%", "43%" )), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))
解决方案
1. 自定义固定顺序
如果已经明确想要的Scenario排列顺序,直接用factor()手动指定levels参数,将处理后的数据传入原绘图代码即可:
# 先修改Scenario的顺序,按你需要的顺序填写levels scenarios_summary_diverging_right_order <- scenarios_summary_diverging_right_order %>% mutate(Scenario = factor(Scenario, levels = c("Scenario 2", "Scenario 1"))) # 原绘图代码不变,直接运行 scenarios_summary_diverging_right_order %>% ggplot(aes(x = Scenario, y = percent_answers, fill = Opinion)) + geom_col() + geom_text(aes(label = percent_answers_label), position = position_stack(vjust = 0.5), color = "white", fontface = "bold") + coord_flip() + scale_x_discrete() + scale_fill_viridis_d(breaks = c("Strongly disagree", "Disagree", "Undecided","Agree", "Strongly agree")) + labs(title = "To what extent do you agree that this is a display of aggressive behaviour?", x = NULL, fill = NULL) + theme_minimal() + theme(axis.text.x = element_blank(), axis.title.x = element_blank(), panel.grid = element_blank(), legend.position = "top")
2. 根据数据指标动态排序
如果想根据某个数值指标(比如某类Opinion的百分比、总回答数等)自动排序,使用forcats::fct_reorder(),注意排序依据必须是数值变量。比如按每个Scenario中"Agree"的百分比从高到低排序:
scenarios_summary_diverging_right_order %>% mutate(Scenario = fct_reorder(Scenario, # 提取每个Scenario中Agree对应的percent_answers作为排序依据 case_when(Opinion == "Agree" ~ percent_answers), .fun = max)) %>% # 每个Scenario仅一行Agree,用max提取对应值 ggplot(aes(x = Scenario, y = percent_answers, fill = Opinion)) + # 后续绘图代码与原代码完全一致 geom_col() + geom_text(aes(label = percent_answers_label), position = position_stack(vjust = 0.5), color = "white", fontface = "bold") + coord_flip() + scale_x_discrete() + scale_fill_viridis_d(breaks = c("Strongly disagree", "Disagree", "Undecided","Agree", "Strongly agree")) + labs(title = "To what extent do you agree that this is a display of aggressive behaviour?", x = NULL, fill = NULL) + theme_minimal() + theme(axis.text.x = element_blank(), axis.title.x = element_blank(), panel.grid = element_blank(), legend.position = "top")
无效代码的问题分析
你之前的尝试存在两个核心问题:
- 颠倒了
x和y的映射关系,原图表是x=Scenario,你改成x=Opinion, y=Scenario,完全改变了图表类型 fct_reorder(Scenario, Opinion)用分类变量Opinion作为排序依据,这是无效的,fct_reorder要求排序依据必须是数值变量(比如percent_answers)
内容的提问来源于stack exchange,提问作者Captain Beaky
相关产品推荐
相关产品推荐

