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

使用geom_rect绘制颜色占比矩形并叠加geom_line展示观测总数

解决方案:用geom_rect展示月度颜色占比 + 叠加总观测数折线

核心思路

要实现geom_rect的堆叠效果,需要先把宽格式的占比数据转成长格式,再计算每个颜色区块的上下边界(ymin/ymax)和左右边界(xmin/xmax),最后合并总观测数数据完成绘图。


步骤1:构造示例数据(模拟你的两个数据框)

先模拟你提到的两个数据结构,方便后续演示:

# 颜色月度占比数据框(宽格式)
color_proportions <- data.frame(
  month = seq.Date(as.Date("2023-01-01"), as.Date("2023-06-01"), by = "month"),
  orange = c(0.2, 0.3, 0.25, 0.15, 0.3, 0.28),
  red = c(0.3, 0.25, 0.2, 0.3, 0.2, 0.22),
  green = c(0.25, 0.2, 0.3, 0.25, 0.25, 0.25),
  yellow = c(0.25, 0.25, 0.25, 0.3, 0.25, 0.25)
)

# 月度总观测数数据框
total_observations <- data.frame(
  month = seq.Date(as.Date("2023-01-01"), as.Date("2023-06-01"), by = "month"),
  total = c(100, 120, 150, 130, 160, 140)
)

步骤2:处理占比数据,生成矩形边界参数

geom_rect需要每个区块的xmin/xmax(月份区间)和ymin/ymax(占比/观测数区间),所以要先做数据转换:

library(tidyverse)

# 1. 宽格式转长格式,方便按颜色分组
color_long <- color_proportions %>%
  pivot_longer(cols = -month, names_to = "color", values_to = "proportion") %>%
  arrange(month, color) # 固定颜色排序,保证堆叠顺序一致

# 2. 计算每个颜色的上下边界(累计占比)
color_long <- color_long %>%
  group_by(month) %>%
  mutate(
    ymin = lag(cumsum(proportion), default = 0), # 上边界:前面所有颜色占比之和
    ymax = cumsum(proportion) # 下边界:到当前颜色的累计占比
  ) %>%
  ungroup()

# 3. 计算每个月份的左右边界(覆盖整个月的时间区间)
color_long <- color_long %>%
  group_by(month) %>%
  mutate(
    xmin = month,
    xmax = lead(month, default = last(month) + months(1)) # 下一个月的日期作为右边界
  ) %>%
  ungroup()

步骤3:绘图(两种可选方案)

方案1:用实际观测数作为Y轴(推荐,无双轴问题)

把占比转换成实际观测数,让矩形和折线共用同一Y轴,更直观:

library(ggplot2)

# 合并总观测数,转换占比为实际观测数
color_long <- color_long %>%
  left_join(total_observations, by = "month") %>%
  mutate(
    ymin_actual = ymin * total,
    ymax_actual = ymax * total
  )

# 绘图
ggplot() +
  # 绘制颜色矩形区块
  geom_rect(data = color_long,
            aes(xmin = xmin, xmax = xmax,
                ymin = ymin_actual, ymax = ymax_actual,
                fill = color),
            color = "white") + # 白色边框区分不同颜色
  # 绘制总观测数折线+点
  geom_line(data = total_observations,
            aes(x = month, y = total),
            color = "black", linewidth = 1) +
  geom_point(data = total_observations,
             aes(x = month, y = total),
             color = "black", size = 2) +
  # 指定颜色填充值
  scale_fill_manual(values = c(orange = "#FFA500", red = "#FF0000", green = "#008000", yellow = "#FFFF00")) +
  # 坐标轴与图例标签
  labs(x = "月份", y = "观测数", fill = "颜色") +
  # 简约主题
  theme_minimal()

方案2:用占比作为Y轴,叠加总观测数双轴

如果需要保留占比Y轴,可通过缩放总观测数实现双轴(注意:双轴可能带来视觉误导,谨慎使用):

# 计算缩放比例,让总观测数适配0-1的占比轴
max_total <- max(total_observations$total)
scale_factor <- 1 / max_total

ggplot() +
  geom_rect(data = color_long,
            aes(xmin = xmin, xmax = xmax,
                ymin = ymin, ymax = ymax,
                fill = color),
            color = "white") +
  geom_line(data = total_observations,
            aes(x = month, y = total * scale_factor),
            color = "black", linewidth = 1) +
  geom_point(data = total_observations,
             aes(x = month, y = total * scale_factor),
             color = "black", size = 2) +
  scale_fill_manual(values = c(orange = "#FFA500", red = "#FF0000", green = "#008000", yellow = "#FFFF00")) +
  # 设置双Y轴
  scale_y_continuous(
    name = "颜色占比",
    sec.axis = sec_axis(~ . / scale_factor, name = "总观测数")
  ) +
  labs(x = "月份", fill = "颜色") +
  theme_minimal()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:52:20