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

在R中基于条形图降序排序并左右拼接Likert图与条形图

问题解决:同步条形图与Likert图的类别排序

需求说明

现有R数据框df,已通过ggplot2、patchwork实现条形图与Likert图拼接,需完成以下调整:

  • 左侧条形图按响应计数降序排列类别
  • 右侧Likert图与条形图的类别排序完全对应

修改方案

核心思路是先从数据中提取按响应计数降序的类别顺序,再将该顺序同步应用到条形图和Likert图的y轴因子中,具体修改点如下:

1. 提前计算类别排序规则

先统计每个类别的总响应数,生成降序排列的类别顺序,后续所有可视化都基于这个顺序:

# 计算每个var的总响应数,得到降序排序的var列表
var_order <- df |>
  count(var) |>
  arrange(desc(n)) |>
  pull(var)

2. 调整条形图的排序

将条形图的var转换为按var_order排序的因子,确保条形图按计数降序排列:

bar_plot <- dat%>%
  select(var,n)%>%
  group_by(var)%>%
  summarise(count = sum(n))%>%
  # 将var转换为按count降序的因子
  mutate(var = factor(var, levels = var_order)) %>%
  ggplot(., aes(y = var, x = count)) +
  geom_bar(stat = "identity", fill = "lightgrey")+labs(x="Response Count",y="")+
  geom_text(aes(label = count),position = position_stack(vjust = .5)) +
  theme_bw()+
  theme(
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank()
  )

3. 同步Likert图的排序

在处理dat数据时,不再用prop_lower排序,而是基于提前生成的var_order来创建y_sort因子,确保Likert图的类别顺序和条形图一致:

dat <- df |>
  mutate(
    across(-var, ~ factor(.x, likert_levels))
  ) |>
  pivot_longer(-var, names_to = "group") |>
  count(var, value, group) |>
  complete(var, value, group, fill = list(n = 0)) |>
  mutate(
    prop = n / sum(n),
    prop_lower = sum(prop[value %in% c("Strongly disagree", "Disagree")]),
    prop_higher = sum(prop[value %in% c("Strongly agree", "Agree")]),
    .by = c(var, group)
  ) |>
  # 按提前定义的var_order排序,而不是prop_lower
  mutate(var = factor(var, levels = var_order)) |>
  arrange(group, var) |>
  mutate(
    y_sort = paste(var, group, sep = "."),
    y_sort = fct_inorder(y_sort)
  )

4. 适配top10筛选逻辑

由于var已转换为因子,筛选top10时直接基于计数即可,无需依赖prop_lower:

top10 <- df |>
  count(var) |>
  arrange(desc(n)) |>
  slice_max(n, n = 10) |>
  pull(var)

dat <- dat |>
  filter(var %in% top10)

完整修改后代码

# Load necessary libraries
library(tibble)
library(tidyverse)
library(ggplot2)
library(ggpubr)
library(ggstats)
library(patchwork)

# Define categories and Likert levels
var_levels <- c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q")

likert_levels <- c(
  "Strongly disagree",
  "Disagree",
  "Neither agree nor disagree",
  "Agree",
  "Strongly agree"
)

# Set seed for reproducibility
set.seed(42)

# Create the dataframe with three Likert response columns
df <- tibble(
  var = sample(var_levels, 50, replace = TRUE),  # Random values from A to Q
  val1 = sample(likert_levels, 50, replace = TRUE) # Random values from Likert levels
)

# 计算每个var的总响应数,得到降序排序的var列表
var_order <- df |>
  count(var) |>
  arrange(desc(n)) |>
  pull(var)

# 筛选top10高响应的类别
top10 <- df |>
  count(var) |>
  arrange(desc(n)) |>
  slice_max(n, n = 10) |>
  pull(var)

# 处理数据用于可视化
dat <- df |>
  mutate(
    across(-var, ~ factor(.x, likert_levels))
  ) |>
  pivot_longer(-var, names_to = "group") |>
  count(var, value, group) |>
  complete(var, value, group, fill = list(n = 0)) |>
  mutate(
    prop = n / sum(n),
    prop_lower = sum(prop[value %in% c("Strongly disagree", "Disagree")]),
    prop_higher = sum(prop[value %in% c("Strongly agree", "Agree")]),
    .by = c(var, group)
  ) |>
  # 应用预定义的var排序
  mutate(var = factor(var, levels = var_order)) |>
  filter(var %in% top10) |>
  arrange(group, var) |>
  mutate(
    y_sort = paste(var, group, sep = "."),
    y_sort = fct_inorder(y_sort)
  )

# 处理总计数据
dat_tot <- dat |>
  distinct(group, var, y_sort, prop_lower, prop_higher) |>
  pivot_longer(-c(group, var, y_sort),
               names_to = c(".value", "name"),
               names_sep = "_"
  ) |>
  mutate(
    hjust_tot = ifelse(name == "lower", 1, 0),
    x_tot = ifelse(name == "lower", -1, 1)
  )

# Bar plot
bar_plot <- dat%>%
  select(var,n)%>%
  group_by(var)%>%
  summarise(count = sum(n))%>%
  mutate(var = factor(var, levels = var_order)) %>%
  ggplot(., aes(y = var, x = count)) +
  geom_bar(stat = "identity", fill = "lightgrey")+labs(x="Response Count",y="")+
  geom_text(aes(label = count),position = position_stack(vjust = .5)) +
  theme_bw()+
  theme(
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.text.x = element_blank(),
    axis.ticks.x = element_blank()
  )

# Likert plot
likert_plot <- ggplot(dat, aes(y = y_sort, x = prop, fill = value)) +
  geom_col(position = position_likert(reverse = FALSE)) +
  geom_text(
    aes(
      label = label_percent_abs(hide_below = .05, accuracy = 1)(prop),
      color = after_scale(hex_bw(.data$fill))
    ),
    position = position_likert(vjust = 0.5, reverse = FALSE),
    size = 3.5
  ) +
  geom_label(
    aes(
      x = x_tot,
      label = label_percent_abs(accuracy = 1)(prop),
      hjust = hjust_tot,
      fill = NULL
    ),
    data = dat_tot,
    size = 3.5,
    color = "black",
    fontface = "bold",
    label.size = 0,
    show.legend = FALSE
  ) +
  scale_y_discrete(labels = \(x) gsub("\\..*$", "", x)) +
  scale_x_continuous(
    labels = label_percent_abs(),
    expand = c(0, .15)
  ) +
  scale_fill_brewer(palette = "BrBG") +
  facet_wrap(~group,
             scales = "free_y", ncol = 1,
             strip.position = "right"
  ) +
  theme_light() +
  theme(
    legend.position = "bottom",
    panel.grid.major.y = element_blank()
  ) +
  labs(x = NULL, y = NULL, fill = NULL)

# 拼接图形
bar_plot + likert_plot + plot_layout(guides = "collect") & theme(legend.position="bottom")

内容的提问来源于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.15 18:49:53