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

在R中用ggplot2使Likert Chart与Bar Plot的Y轴排序一致

解决Likert图与条形图Y轴类别顺序不一致的问题

我在R中生成了名为df的随机数据框,计划使用ggplot2绘制水平Likert Chart和Bar Plot。当前两张图表的Y轴类别顺序不匹配(Likert Chart从上到下为B、A、D、C,Bar Plot为D、C、B、A),如何实现两者Y轴类别排序完全一致?相关代码及示例图如下:

library(tibble)
library(dplyr)
library(tidyr)
library(ggplot2)
library(ggstats)
library(ggpubr)

var_levels <- c("A", "B", "C", "D")
likert_levels <- c(
  "Strongly disagree",
  "Disagree",
  "Neither agree nor disagree",
  "Agree",
  "Strongly agree"
)

set.seed(42)
df <- tibble(
  var = sample(var_levels, 50, replace = TRUE),  # 从A到D随机取值
  val = sample(likert_levels, 50, replace = TRUE)  # 从Likert等级随机取值
)

df2 <- df %>%
  mutate(across(everything(), as.factor)) %>%
  group_by(var) %>%
  mutate(row = row_number()) %>%
  pivot_wider(names_from = var,   # 'var'中的值将成为新列名
              values_from = val) %>%
  select(-row)

v1 = ggstats::gglikert(df2)+
  aes(y = reorder(.question,
                  ifelse(
                    .answer %in% c("Strongly disagree", "Disagree"),
                    1, 0),FUN = sum),decreasing=TRUE)

df_total = df %>%
  count(var,val) %>%
  group_by(var) %>%
  mutate(pct = round(prop.table(n) * 100, 1)) %>%
  select(-n) %>%
  filter(!is.na(val)) %>%
  pivot_wider(names_from = val, values_from = pct)
colnames(df_total) = c("var",likert_levels)
df_total  = df_total %>%
  mutate(order = `Strongly disagree` + Disagree ) %>%
  arrange(desc(order))

v2 = df %>%
  mutate(across(everything(), as.factor)) %>%
  group_by(var) %>%
  summarise(count=n()) %>%
  ggplot(., aes(x = var, y = count)) +
  geom_bar(stat = "identity", fill = "lightgrey")+
  coord_flip()

ggarrange(v1,v2,widths = c(6,2))

Y轴顺序不一致的示例图


解决方案

要统一两个图表的Y轴顺序,核心是让两个图表使用完全相同的因子水平顺序,这里提供两种直接可行的方法:

方法一:提取Likert图的排序并复用

先从已生成的Likert图中提取Y轴类别顺序,再将其应用到条形图的因子设置中:

# 提取Likert图的Y轴类别顺序
likert_order <- ggplot_build(v1)$layout$panel_params[[1]]$y$get_labels()

# 修改条形图代码,应用统一顺序
v2 <- df %>%
  mutate(across(everything(), as.factor)) %>%
  group_by(var) %>%
  summarise(count = n()) %>%
  # 关键:按照Likert图的顺序重新设置var的因子水平
  mutate(var = factor(var, levels = likert_order)) %>%
  ggplot(., aes(x = var, y = count)) +
  geom_bar(stat = "identity", fill = "lightgrey") +
  coord_flip()

方法二:提前统一排序规则(更可控)

如果希望提前定义排序逻辑(和Likert图中reorder的规则一致),可以在数据预处理阶段就统一设置var的因子水平:

# 计算每个var的"不同意"类别的总和,作为排序依据
sort_order <- df %>%
  mutate(score = ifelse(val %in% c("Strongly disagree", "Disagree"), 1, 0)) %>%
  group_by(var) %>%
  summarise(total = sum(score)) %>%
  arrange(desc(total)) %>%
  pull(var)

# 统一设置df中var的因子水平
df <- df %>% mutate(var = factor(var, levels = sort_order))

# 绘制Likert图(无需再用reorder,直接使用已排序的因子)
v1 <- ggstats::gglikert(df2) + aes(y = .question)

# 绘制条形图(自动使用已排序的因子)
v2 <- df %>%
  group_by(var) %>%
  summarise(count = n()) %>%
  ggplot(., aes(x = var, y = count)) +
  geom_bar(stat = "identity", fill = "lightgrey") +
  coord_flip()

内容的提问来源于stack exchange,提问作者Homer Jay Simpson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 07:16:11