如何在时间序列图X轴仅在当年首次出现时显示年份标签
实现跨年度时间序列图的X轴刻度自定义格式
要实现X轴仅在每年首个月份显示「年份-月份」,其余月份仅显示月份的效果,或者将年份单独置于月份下方,可以通过自定义标签函数结合ggplot2的刻度设置完成,以下是两种可行方案:
方案1:直接在首个月份显示年份+月份
通过自定义标签函数,判断每个刻度日期是否为对应年份的第一个出现项,再分别应用不同格式:
library(tidyverse) set.seed(123) df_test <- tibble( date = seq(as.Date("2010-1-1"), as.Date("2012-1-1"), by = "months"), value = rnorm(n = length(date), mean = 10, sd = 1) ) # 自定义日期标签函数 custom_date_labels <- function(x) { years <- lubridate::year(x) months <- lubridate::month(x, label = TRUE, abbr = TRUE) # 判断是否为该年份的第一个刻度 is_first_in_year <- !duplicated(years) # 生成对应标签 ifelse(is_first_in_year, paste(years, months, sep = "-"), as.character(months)) } # 绘制图表 gg_full <- df_test %>% ggplot(aes(x = date, y = value)) + geom_line() + scale_x_date( date_breaks = "1 month", labels = custom_date_labels) + theme( axis.text.x = element_text(angle = 45, hjust = 1)) gg_full
方案2:年份单独置于月份下方(层级更清晰)
借助ggtext包支持的Markdown格式,将年份作为第二行显示在月份下方,视觉区分度更高:
library(tidyverse) library(ggtext) set.seed(123) df_test <- tibble( date = seq(as.Date("2010-1-1"), as.Date("2012-1-1"), by = "months"), value = rnorm(n = length(date), mean = 10, sd = 1) ) # 自定义多行标签函数 custom_multi_labels <- function(x) { years <- lubridate::year(x) months <- lubridate::month(x, label = TRUE, abbr = TRUE) is_first_in_year <- !duplicated(years) # 生成带换行的Markdown标签,年份字号缩小 labels <- ifelse(is_first_in_year, paste0(months, "<br><span style='font-size:70%'>", years, "</span>"), as.character(months)) return(labels) } # 绘制图表 gg_multi <- df_test %>% ggplot(aes(x = date, y = value)) + geom_line() + scale_x_date( date_breaks = "1 month", labels = custom_multi_labels) + theme( axis.text.x = element_markdown(angle = 0, hjust = 0.5)) # 用element_markdown解析换行 gg_multi
说明
- 两个方案中,
!duplicated(years)会自动识别每个年份在X轴刻度中的第一个出现项,即便数据起始月份不是1月也能正常工作。 - 方案2通过
ggtext的element_markdown支持HTML样式调整,可根据需求修改字体大小、颜色等样式。
内容的提问来源于stack exchange,提问作者Cameron
相关产品推荐
相关产品推荐

