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

调整R ggplot2金字塔图图例项顺序,匹配性别区域

调整ggplot2金字塔图的图例项顺序问题

问题背景

需要调整R ggplot2金字塔图的图例项顺序,使图例中的Males对应图中的男性区域,Females对应女性区域。之前尝试执行以下代码时出现错误:

# Change the order of values to reflect them in the plot
pop_hisp_df$Type = factor(pop_hisp_df$Type, levels = rev(pop_hisp_df$Type))

错误信息:

Error in `levels<-`(`*tmp*`, value = as.character(levels)) : 
  factor level [2] is duplicated

数据与现有代码

数据(pop_hisp_df)

structure(list(age_group = c("<  5 years", "5 - 14", "15  -  24", 
"25  -  34", "35  -  44", "45  -  54", "55  -  64", "65  -  74", 
"75  -  84", "85 +", "<  5 years", "5 - 14", "15  -  24", "25  -  34", 
"35  -  44", "45  -  54", "55  -  64", "65  -  74", "75  -  84", 
"85 +"), Type = c("Males", "Males", "Males", "Males", "Males", 
"Males", "Males", "Males", "Males", "Males", "Females", "Females", 
"Females", "Females", "Females", "Females", "Females", "Females", 
"Females", "Females"), Value = c(-6, -13, -13, -15, -17, -15, 
-11, -6, -3, -1, 6, 12, 12, 14, 16, 15, 12, 7, 4, 2)), row.names = c(NA, 
-20L), class = c("tbl_df", "tbl", "data.frame"))

现有绘图代码

library(tidyverse)
library(plotly)

# Plot
gg_pop_hisp = ggplot(pop_hisp_df, aes( x = forcats::as_factor(age_group), y = Value, fill = Type)) +
  geom_bar(data = subset(pop_hisp_df, Type == "Females"), stat = "identity") +
  geom_bar(data = subset(pop_hisp_df, Type == "Males"), stat = "identity") +
  #geom_text(aes(label = paste0(abs(Value), "%"))) +
  scale_y_continuous(limits=c(-20,20),
                     breaks=c(-15,-10,0,10,15),
                     labels=paste0(c(15,10,0,10,15),"%")) +          # CHANGE
  scale_fill_manual(name = "", values = c("Females"="#FC921F", "Males"="#149ECE"), labels = c("Females", "Males")) +
  ggtitle("HISPANIC POPULATION BY GENDER AND AGE GROUP") +
  labs(x = "AGE GROUPS", y = "PERCENTAGE POPULATION", fill = "Gender") +
  theme_minimal() +
  theme(legend.position="bottom") +
  coord_flip()  

# Interactive
ggplotly(gg_pop_hisp) %>% 
  layout(
    legend = list(
      orientation = 'h', x = 0.3, y = -0.3, 
      title = list(text = '')))

解决方案

错误原因分析

之前的代码报错是因为rev(pop_hisp_df$Type)会生成包含重复值的向量(每个性别重复10次),而因子的level必须是唯一的,因此触发重复level错误。

正确修改步骤

要让图例项顺序与图中区域对应,只需两步:

  1. 手动设置Type因子的水平顺序:指定唯一的level值,而非用整列数据反转
  2. 同步调整scale_fill_manual的参数:确保颜色、标签与因子水平对应

修改后的完整代码

library(tidyverse)
library(plotly)

# 第一步:正确设置Type因子的水平顺序(按需要的图例顺序)
pop_hisp_df$Type = factor(pop_hisp_df$Type, levels = c("Males", "Females"))

# Plot
gg_pop_hisp = ggplot(pop_hisp_df, aes( x = forcats::as_factor(age_group), y = Value, fill = Type)) +
  geom_bar(data = subset(pop_hisp_df, Type == "Females"), stat = "identity") +
  geom_bar(data = subset(pop_hisp_df, Type == "Males"), stat = "identity") +
  #geom_text(aes(label = paste0(abs(Value), "%"))) +
  scale_y_continuous(limits=c(-20,20),
                     breaks=c(-15,-10,0,10,15),
                     labels=paste0(c(15,10,0,10,15),"%")) +
  # 第二步:同步调整scale_fill_manual的values和labels顺序,与因子水平对应
  scale_fill_manual(name = "", 
                    values = c("Males"="#149ECE", "Females"="#FC921F"), 
                    labels = c("Males", "Females")) +
  ggtitle("HISPANIC POPULATION BY GENDER AND AGE GROUP") +
  labs(x = "AGE GROUPS", y = "PERCENTAGE POPULATION", fill = "Gender") +
  theme_minimal() +
  theme(legend.position="bottom") +
  coord_flip()  

# Interactive
ggplotly(gg_pop_hisp) %>% 
  layout(
    legend = list(
      orientation = 'h', x = 0.3, y = -0.3, 
      title = list(text = '')))

关键修改说明

  • 因子水平设置:levels = c("Males", "Females")指定了图例的显示顺序,先显示Males,再显示Females
  • scale_fill_manual参数:values的顺序与因子水平对应,确保Males对应蓝色(#149ECE),Females对应橙色(#FC921F),同时labels也保持一致顺序,这样图例项就会和图中的区域完全匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:36:15