在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))
错误原因
- 数据格式问题:原代码用两个宽格式数据集分别绘制折线,颜色映射是手动传入的字符串,directlabels无法正确识别这种离散型分组关系
- 日期轴处理错误:用
scale_x_continuous处理日期数据(本质是特殊连续型),和离散颜色映射产生冲突 - 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
相关产品推荐
相关产品推荐

