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

在ggplot双geom_line图中添加direct label报错求助

问题解决:双折线图添加direct label时的“Continuous value supplied to discrete scale”错误

问题描述

尝试用directlabels包为两幅geom_line折线图添加直接标签,反复尝试后始终触发“Continuous value supplied to discrete scale”错误,以下是原数据处理及绘图代码:

living = c("insurance", "housing", "utilities", "food", "transportation", "healthcare", "debt")
discretionary = c("recreation", "personal", "gifts", "vacation")

dat2 = dat %>%
group_by(month = lubridate::floor_date(date, "month")) %>%
filter(category %in% living) %>%
summarise(cost_of_living_spending = sum(amount))

dat3 = dat %>%
group_by(month = lubridate::floor_date(date, "month")) %>%
filter(category %in% discretionary) %>%
summarise(discretionary_spending = sum(amount))

gg = ggplot() +
geom_line(data = dat2, aes(x = month, y = cost_of_living_spending, group = 1, color = "cost_of_living_spending"),
linewidth = 0.8, stat = "identity") +
geom_line(data = dat3, aes(x = month, y = discretionary_spending, group = 1, color = "discretionary_spending"),
linewidth = 0.8, stat = "identity") +
ggtitle("Comparison between living and discretionary spending over time") +
scale_color_manual(values = c("#FFC20A", "#0C7BDC" )) +
scale_x_continuous(name = "date", breaks = seq.Date(as.Date("2018-06-01"), as.Date("2022-12-01"), by = "6 months"), labels = c("2018.06.", "2018.12.", "2019.06.", "2019.12.", "2020.06", "2020.12.", "2021.06.", "2021.12.", "2022.06.", "2022.12.")) +
scale_y_continuous(name = "spending ($)", limits = c(0, 10000), breaks = seq(0, 10000, 2500)) +
theme(plot.background = element_rect(fill = "gray96"),
panel.background = element_rect(fill = "gray96"),
panel.grid.major.x = element_line(color = "gray88"),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_line(color = "gray88", size = 0.3, linetype = 1),
panel.grid.minor.y = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(size = 12, color = 'black'),
plot.subtitle = element_text(size = 10),
axis.title.x = element_text(size = 10),
axis.title.y = element_text(size = 10),
axis.text.x = element_text(size = 8),
axis.text.y = element_text(size = 8))
gg

direct.label(gg, aes(color = color))

错误原因

  1. 数据格式问题:原代码用两个宽格式数据集分别绘制折线,颜色映射是手动传入的字符串,directlabels无法正确识别这种离散型分组关系
  2. 日期轴处理错误:用scale_x_continuous处理日期数据(本质是特殊连续型),和离散颜色映射产生冲突
  3. directlabels调用方式错误:direct.label(gg, aes(color = color))的映射逻辑不匹配当前的绘图结构

修正方案

步骤1:转换为长格式数据

将两个数据集合并为长格式,统一用一个离散型变量标记支出类型,让ggplot自动处理颜色和分组映射

步骤2:修正日期轴刻度

用scale_x_date替代scale_x_continuous,专门处理日期类型数据,避免类型冲突

步骤3:正确调用directlabels

使用内置的位置调整函数(如last.qp)自动放置标签,无需手动指定映射

修正后完整代码

library(tidyverse)
library(lubridate)
library(directlabels)

# 定义支出分类
living = c("insurance", "housing", "utilities", "food", "transportation", "healthcare", "debt")
discretionary = c("recreation", "personal", "gifts", "vacation")

# 转换为长格式数据
dat_long = dat %>%
  group_by(month = floor_date(date, "month")) %>%
  # 创建支出类型分组变量
  mutate(
    spending_type = case_when(
      category %in% living ~ "cost_of_living_spending",
      category %in% discretionary ~ "discretionary_spending",
      TRUE ~ NA_character_
    )
  ) %>%
  filter(!is.na(spending_type)) %>%
  # 按月份和支出类型汇总支出
  summarise(spending = sum(amount), .by = c(month, spending_type))

# 绘制折线图
gg = ggplot(dat_long, aes(x = month, y = spending, color = spending_type, group = spending_type)) +
  geom_line(linewidth = 0.8) +
  ggtitle("生活成本与可支配支出对比(2018-2022)") +
  # 自定义颜色映射
  scale_color_manual(
    values = c("#FFC20A", "#0C7BDC"),
    labels = c("生活成本支出", "可支配支出")
  ) +
  # 使用日期专用刻度函数
  scale_x_date(
    name = "日期",
    breaks = seq.Date(as.Date("2018-06-01"), as.Date("2022-12-01"), by = "6 months"),
    labels = function(x) format(x, "%Y.%m.")
  ) +
  scale_y_continuous(
    name = "支出 ($)",
    limits = c(0, 10000),
    breaks = seq(0, 10000, 2500)
  ) +
  # 保留原主题设置
  theme(
    plot.background = element_rect(fill = "gray96"),
    panel.background = element_rect(fill = "gray96"),
    panel.grid.major.x = element_line(color = "gray88"),
    panel.grid.minor.x = element_blank(),
    panel.grid.major.y = element_line(color = "gray88", size = 0.3, linetype = 1),
    panel.grid.minor.y = element_blank(),
    axis.ticks = element_blank(),
    plot.title = element_text(size = 12, color = 'black'),
    plot.subtitle = element_text(size = 10),
    axis.title.x = element_text(size = 10),
    axis.title.y = element_text(size = 10),
    axis.text.x = element_text(size = 8),
    axis.text.y = element_text(size = 8)
  )

# 添加direct label,将标签放在折线末尾
direct.label(gg, "last.qp")

可选调整

如果需要将标签放在其他位置,可以替换"last.qp"为以下参数:

  • "first.qp":折线起始位置
  • "top.qp":折线最高位置
  • "bottom.qp":折线最低位置
  • "angled.boxes":带背景框的倾斜标签

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 10:27:07