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

geom_point与geom_boxplot用不同颜色变量时公司代码配色序列异常

问题解决:添加箱线图后数据点配色序列失效

问题场景

我需要生成这样的图表:每个财年下的各公司数据点按特定序列渐变配色,背景叠加对应财年的箱线图。原本通过arrange+mutate(fct_inorder())把company_code转为有序因子,以此控制配色序列,但添加geom_boxplot(aes(colour=financial_year))后,数据点的配色变得随机,移除箱线图层则配色序列恢复正常。

示例代码:

library(dplyr); library(forcats)
df1 %>% arrange(financial_year != "2018-19", -production) %>%
  mutate(company_code = fct_inorder(as.factor(company_code))) %>%
  arrange(company_code, financial_year) %>%
  ggplot(., mapping = aes(x=financial_year, y = production))+
       geom_point(aes(colour=company_code),position = position_jitter(height=0, width=0.2),
                  size = 1.1, alpha = 0.6) + geom_boxplot(aes(colour=financial_year))

示例数据:

company_code <- c(1,1,1,1,2,2,2,2,3,3,3,3)
financial_year <- c("2018-19","2019-20","2020-21","2018-21","2018-19","2019-20","2020-21","2018-21","2018-19","2019-20","2020-21","2018-21")
production <- c(2000,2500,3000,7500,1000,1500,1000,3500,5000,5500,4000,14500)

df <- data.frame(company_code,financial_year,production)
df$company_code <- as.factor(df$company_code)
df$financial_year <- as.factor(df$financial_year)

原因分析

ggplot中同一个绘图上下文不能同时绑定两个独立的colour美学映射。当给geom_boxplot添加aes(colour=financial_year)后,ggplot会重置全局颜色标尺,覆盖掉之前通过有序因子company_code设定的配色序列规则,导致数据点颜色随机分配。

解决方案

方案1:手动固定公司配色序列

直接用scale_colour_manual指定company_code的颜色,同时给箱线图单独设置固定颜色,避免映射冲突:

library(dplyr); library(forcats); library(ggplot2)

# 按需求定义公司配色序列
company_colors <- c("1" = "#1f77b4", "2" = "#ff7f0e", "3" = "#2ca02c")

df %>% 
  arrange(financial_year != "2018-19", -production) %>%
  mutate(company_code = fct_inorder(as.factor(company_code))) %>%
  ggplot(aes(x=financial_year, y = production))+
  # 箱线图用固定灰色边框,不绑定colour映射
  geom_boxplot(colour = "gray50", alpha = 0.2) +
  # 数据点使用手动定义的配色序列
  geom_point(aes(colour=company_code), 
             position = position_jitter(height=0, width=0.2),
             size = 1.1, alpha = 0.6) +
  scale_colour_manual(values = company_colors)

方案2:用fill替代箱线图的colour映射

如果不需要箱线图边框颜色对应财年,改用填充色区分财年,这样就不会和数据点的colour映射冲突:

library(dplyr); library(forcats); library(ggplot2)

df %>% 
  arrange(financial_year != "2018-19", -production) %>%
  mutate(company_code = fct_inorder(as.factor(company_code))) %>%
  ggplot(aes(x=financial_year, y = production))+
  # 箱线图用fill映射财年,边框统一为黑色
  geom_boxplot(aes(fill=financial_year), colour = "black", alpha = 0.2) +
  # 数据点的colour映射不受影响
  geom_point(aes(colour=company_code), 
             position = position_jitter(height=0, width=0.2),
             size = 1.1, alpha = 0.6) +
  # 可选:给fill设置渐变配色
  scale_fill_viridis_d(alpha = 0.3)

方案3:用ggnewscale创建多组独立颜色标尺

如果必须让箱线图边框颜色对应财年,同时保留数据点的配色序列,可以用ggnewscale包创建独立的颜色标尺:

library(dplyr); library(forcats); library(ggplot2); library(ggnewscale)

df %>% 
  arrange(financial_year != "2018-19", -production) %>%
  mutate(company_code = fct_inorder(as.factor(company_code))) %>%
  ggplot(aes(x=financial_year, y = production))+
  # 先绘制数据点,绑定company_code的colour映射
  geom_point(aes(colour=company_code), 
             position = position_jitter(height=0, width=0.2),
             size = 1.1, alpha = 0.6) +
  scale_colour_viridis_d() +
  # 新建独立的颜色标尺用于箱线图
  new_scale_colour() +
  geom_boxplot(aes(colour=financial_year))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:09:21