如何在R的gglikert中按‘同意+非常同意’总和排序分面子图?
基于gglikert实现分面子图按“同意类选项总和”排序
使用ggstats库的模拟数据(代码见下文),需要让gglikert生成的每个分面子图,按照**"Strongly agree"(非常同意)和"Agree"(同意)的总和**进行排序,具体实现方法如下:
可复现模拟数据
library(ggstats) library(dplyr) library(ggplot2) # 定义李克特量表水平 likert_levels <- c( "Strongly disagree", "Disagree", "Neither agree nor disagree", "Agree", "Strongly agree" ) set.seed(42) df <- tibble( q1 = sample(likert_levels, 150, replace = TRUE), q2 = sample(likert_levels, 150, replace = TRUE, prob = 5:1), q3 = sample(likert_levels, 150, replace = TRUE, prob = 1:5), q4 = sample(likert_levels, 150, replace = TRUE, prob = 1:5), q5 = sample(c(likert_levels, NA), 150, replace = TRUE), q6 = sample(likert_levels, 150, replace = TRUE, prob = c(1, 0, 1, 1, 0)) ) |> mutate(across(everything(), ~ factor(.x, levels = likert_levels))) # 添加分组变量 df_group <- df df_group$group1 <- sample(c("A", "B"), 150, replace = TRUE) df_group$group2 <- sample(c("a", "b", "c"), 150, replace = TRUE)
实现排序的核心思路
要让分面内的子图按同意类选项总和排序,需先计算每个分面组下各问题的同意总和,重新定义问题变量的因子水平顺序后,再传入gglikert。
场景1:仅按列分面(facet_cols = group1)
# 1. 转换为长格式,计算每个group1分组下各问题的同意总和 rank_df <- df_group |> pivot_longer(q1:q6, names_to = "question", values_to = "response") |> filter(!is.na(response)) |> group_by(group1, question) |> summarise(agree_total = sum(response %in% c("Agree", "Strongly agree")), .groups = "drop") |> # 按group1分组,对同意总和降序排序,确定问题顺序 group_by(group1) |> arrange(desc(agree_total)) |> mutate(question_order = factor(question, levels = unique(question))) # 2. 将原数据的问题变量转换为排序后的因子 df_group_sorted <- df_group |> pivot_longer(q1:q6, names_to = "question", values_to = "response") |> left_join(rank_df |> select(group1, question, question_order), by = c("group1", "question")) |> pivot_wider(names_from = question, values_from = response) |> mutate(across(q1:q6, ~ factor(.x, levels = likert_levels))) # 3. 绘制排序后的likert图 gglikert(df_group_sorted, q1:q6, facet_cols = vars(group1), labels_size = 3)
场景2:按行和列分面(facet_rows = group2, facet_cols = group1)
# 1. 计算每个group1+group2组合下各问题的同意总和 rank_df_2 <- df_group |> pivot_longer(q3:q6, names_to = "question", values_to = "response") |> filter(!is.na(response)) |> group_by(group1, group2, question) |> summarise(agree_total = sum(response %in% c("Agree", "Strongly agree")), .groups = "drop") |> # 按group1+group2分组,对同意总和降序排序 group_by(group1, group2) |> arrange(desc(agree_total)) |> mutate(question_order = factor(question, levels = unique(question))) # 2. 转换原数据的问题变量为排序后的因子 df_group_sorted_2 <- df_group |> pivot_longer(q3:q6, names_to = "question", values_to = "response") |> left_join(rank_df_2 |> select(group1, group2, question, question_order), by = c("group1", "group2", "question")) |> pivot_wider(names_from = question, values_from = response) |> mutate(across(q3:q6, ~ factor(.x, levels = likert_levels))) # 3. 绘制排序后的likert图 gglikert(df_group_sorted_2, q3:q6, facet_cols = vars(group1), facet_rows = vars(group2), labels_size = 3) + scale_x_continuous( labels = label_percent_abs(), expand = expansion(0, .2) )
补充说明
- 代码默认按同意总和降序排序,若需升序,将
arrange(desc(agree_total))改为arrange(agree_total)即可; - 计算总和时也可改用百分比(如
agree_pct = mean(response %in% c("Agree", "Strongly agree"))),排序逻辑一致。
内容的提问来源于stack exchange,提问作者Homer Jay Simpson
相关产品推荐
相关产品推荐

