You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:11:01