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

R中分面网格条形图排序及变化百分比标注问题

解决分面条形图排序、颜色匹配及百分比标注问题

一、修正颜色与图例不匹配问题

你当前的条形颜色和图例顺序不对应,核心问题有两个:

  1. 数据大小写不一致:原始数据中Active_period是Last_year(首字母大写),但代码里用的是last_year(全小写),导致因子映射失效。
  2. 颜色映射顺序错位:scale_fill_manual的values顺序和limits不匹配,造成颜色对应错误。

修正后的基础代码

library(ggplot2)
library(dplyr)
library(tidyr)

# 统一Active_period的大小写,修正数据中的Last_year为last_year
data <- data %>%
  mutate(Active_period = tolower(Active_period))

# 正确设置因子水平,确保顺序符合需求
data$Active_period <- factor(data$Active_period, 
                             levels = c("study_year", "last_year", "this_year"))

# 绘制基础图,颜色顺序与因子水平对齐
ggplot(data, aes(count, Name, fill = Active_period)) +
  geom_col(width = 0.8, position = position_dodge2(width = 0.8, preserve = "single"))+
  facet_grid(Time ~ site)+
  scale_fill_manual(name = " ",
                    values = c("study_year" ="#5d5c5c", 
                               "last_year" = "#333239",
                               "this_year" ="#4475aa"), # 与因子水平顺序完全对应
                    limits = c("study_year","last_year", "this_year"))+
  theme(legend.position = "bottom", 
        axis.text = element_text(size = 11), 
        axis.title = element_text(size = 11, face = "bold"),
        strip.text.x = element_text(size = 12),
        strip.text.y = element_text(size = 12),
        plot.title = element_text(size = 14, face = "bold"),
        plot.subtitle = element_text(size = 13))

二、实现分面内条形排序

要让每个分面(Time+site组合)里的Name按指定指标排序(比如按this_year的count降序),可以先计算排序规则,再将Name转为因子:

# 按每个Time+site组合,以this_year的count为依据排序Name
sorted_names <- data %>%
  filter(Active_period == "this_year") %>%
  arrange(Time, site, desc(count)) %>%
  group_by(Time, site) %>%
  mutate(Name_order = row_number()) %>%
  ungroup() %>%
  select(Name, Time, site, Name_order)

# 合并排序规则到原数据,将Name转为对应分面的排序因子
data <- data %>%
  left_join(sorted_names, by = c("Name", "Time", "site")) %>%
  group_by(Time, site) %>%
  mutate(Name = factor(Name, levels = unique(Name[order(Name_order)]))) %>%
  ungroup()

# 重新绘图,开启free_y避免空类别占位
ggplot(data, aes(count, Name, fill = Active_period)) +
  geom_col(width = 0.8, position = position_dodge2(width = 0.8, preserve = "single"))+
  facet_grid(Time ~ site, scales = "free_y")+
  scale_fill_manual(name = " ",
                    values = c("study_year" ="#5d5c5c", 
                               "last_year" = "#333239",
                               "this_year" ="#4475aa"),
                    limits = c("study_year","last_year", "this_year"))+
  theme(legend.position = "bottom", 
        axis.text = element_text(size = 11), 
        axis.title = element_text(size = 11, face = "bold"),
        strip.text.x = element_text(size = 12),
        strip.text.y = element_text(size = 12),
        plot.title = element_text(size = 14, face = "bold"),
        plot.subtitle = element_text(size = 13))

三、标注条形间变化百分比

以标注this_year相对last_year的变化率为例,先计算百分比,再用geom_text添加标注:

# 转换数据格式,计算变化百分比
percent_data <- data %>%
  pivot_wider(names_from = Active_period, values_from = count) %>%
  mutate(
    # 计算last_year到this_year的变化率,处理除零报错情况
    change_last_to_this = ifelse(last_year == 0, NA, ((this_year - last_year)/last_year)*100)
  ) %>%
  # 转回长格式,方便与条形位置对齐
  pivot_longer(cols = c(study_year, last_year, this_year), 
               names_to = "Active_period", values_to = "count")

# 绘图并添加百分比标注
ggplot(data, aes(count, Name, fill = Active_period)) +
  geom_col(width = 0.8, position = position_dodge2(width = 0.8, preserve = "single"))+
  # 在this_year条形右侧标注变化率
  geom_text(data = percent_data %>% filter(Active_period == "this_year"),
            aes(x = count + 10, # 调整x轴偏移量避免重叠
                label = ifelse(!is.na(change_last_to_this), 
                               paste0(round(change_last_to_this, 1), "%"), "")),
            position = position_dodge2(width = 0.8),
            size = 3.5)+
  facet_grid(Time ~ site, scales = "free_y")+
  scale_fill_manual(name = " ",
                    values = c("study_year" ="#5d5c5c", 
                               "last_year" = "#333239",
                               "this_year" ="#4475aa"),
                    limits = c("study_year","last_year", "this_year"))+
  theme(legend.position = "bottom", 
        axis.text = element_text(size = 11), 
        axis.title = element_text(size = 11, face = "bold"),
        strip.text.x = element_text(size = 12),
        strip.text.y = element_text(size = 12),
        plot.title = element_text(size = 14, face = "bold"),
        plot.subtitle = element_text(size = 13))

如果需要标注其他对比(如this_year vs study_year),只需在percent_data中新增对应的计算列即可。

内容的提问来源于stack exchange,提问作者GeoBeez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:52:04