在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轴顺序,核心是让两个图表使用完全相同的因子水平顺序,这里提供两种直接可行的方法:
方法一:提取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
相关产品推荐
相关产品推荐

