如何在多年份数据的X轴仅显示月份,同时按日绘制数据点?
问题描述
我有一份包含调查计数的数据集,想要绘制X轴为日期、Y轴为计数的折线图,每年的数据对应一条折线。我希望X轴仅显示月份,但数据点仍按具体日期绘制(类似仅用月-日作为横轴的效果,且不同年份的同日期点要对齐)。
我知道单年份数据可以用scale_x_date实现,但因为是多年份数据,日期不能包含年份,且找不到简便方法将月-日(MD列)转换为Date类。
数据集如下:
structure(list(Date = structure(c(15218, 15274, 15314, 15392, 15429, 15441, 15463, 15547, 15574, 15607, 15652, 15687, 15742, 15768, 15799, 15825, 15853, 15898, 15938, 15982, 16009, 16035, 16073, 16098, 16126, 16128, 16147, 16149, 16181, 16225, 16252, 16288, 16331, 16358, 16378, 16407, 16464, 16465, 16525, 16554, 16583, 16610, 16645, 16667, 16696, 16720, 16749, 16798, 16815, 16862, 16891, 16918, 16947, 16976, 17010, 17038, 17072, 17100, 17123, 17150, 17176, 17198, 17220, 17268, 17296, 17329, 17372, 17421, 17491, 17571, 17617, 17647, 17725, 17773, 17792, 17834, 17863, 17884, 17920, 17955, 17987, 18014, 18058, 18096, 18131, 18156, 18186, 18212, 18240, 18306, 18401, 18432, 18464, 18465, 18485, 18526, 18557, 18590, 18616, 18652, 18711, 18744, 18771, 18796, 18835, 18858, 18892, 18915, 18954, 18977, 19023, 19045, 19081, 19101, 19130, 19165, 19199, 19221, 19251, 19287, 19310, 19339), class = "Date"), thecount = c(7L, 11L, 11L, 8L, 9L, 4L, 5L, 4L, 2L, 7L, 4L, 7L, 7L, 6L, 13L, 9L, 4L, 6L, 6L, 5L, 6L, 9L, 10L, 10L, 10L, 14L, 11L, 12L, 5L, 6L, 9L, 6L, 7L, 14L, 8L, 9L, 6L, 7L, 7L, 3L, 9L, 5L, 7L, 5L, 10L, 9L, 10L, 12L, 9L, 11L, 16L, 9L, 10L, 5L, 5L, 8L, 10L, 9L, 12L, 8L, 8L, 8L, 2L, 4L, 3L, 7L, 4L, 6L, 5L, 5L, 9L, 9L, 4L, 8L, 7L, 5L, 4L, 3L, 7L, 5L, 6L, 7L, 6L, 4L, 10L, 4L, 5L, 2L, 4L, 14L, 9L, 5L, 4L, 3L, 4L, 6L, 3L, 3L, 5L, 9L, 8L, 4L, 6L, 4L, 7L, 3L, 5L, 5L, 5L, 17L, 21L, 13L, 20L, 7L, 3L, 20L, 5L, 9L, 10L, 5L, 11L, 16L), Year = c("2011", "2011", "2011", "2012", "2012", "2012", "2012", "2012", "2012", "2012", "2012", "2012", "2013", "2013", "2013", "2013", "2013", "2013", "2013", "2013", "2013", "2013", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2014", "2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", "2015", "2016", "2016", "2016", "2016", "2016", "2016", "2016", "2016", "2016", "2016", "2016", "2016", "2017", "2017", "2017", "2017", "2017", "2017", "2017", "2017", "2017", "2018", "2018", "2018", "2018", "2018", "2018", "2018", "2018", "2018", "2019", "2019", "2019", "2019", "2019", "2019", "2019", "2019", "2019", "2019", "2019", "2020", "2020", "2020", "2020", "2020", "2020", "2020", "2020", "2020", "2020", "2021", "2021", "2021", "2021", "2021", "2021", "2021", "2021", "2021", "2021", "2021", "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022"), MD = c("09-01", "10-27", "12-06", "02-22", "03-30", "04-11", "05-03", "07-26", "08-22", "09-24", "11-08", "12-13", "02-06", "03-04", "04-04", "04-30", "05-28", "07-12", "08-21", "10-04", "10-31", "11-26", "01-03", "01-28", "02-25", "02-27", "03-18", "03-20", "04-21", "06-04", "07-01", "08-06", "09-18", "10-15", "11-04", "12-03", "01-29", "01-30", "03-31", "04-29", "05-28", "06-24", "07-29", "08-20", "09-18", "10-12", "11-10", "12-29", "01-15", "03-02", "03-31", "04-27", "05-26", "06-24", "07-28", "08-25", "09-28", "10-26", "11-18", "12-15", "01-10", "02-01", "02-23", "04-12", "05-10", "06-12", "07-25", "09-12", "11-21", "02-09", "03-27", "04-26", "07-13", "08-30", "09-18", "10-30", "11-28", "12-19", "01-24", "02-28", "04-01", "04-28", "06-11", "07-19", "08-23", "09-17", "10-17", "11-12", "12-10", "02-14", "05-19", "06-19", "07-21", "07-22", "08-11", "09-21", "10-22", "11-24", "12-20", "01-25", "03-25", "04-27", "05-24", "06-18", "07-27", "08-19", "09-22", "10-15", "11-23", "12-16", "01-31", "02-22", "03-30", "04-19", "05-18", "06-22", "07-26", "08-17", "09-16", "10-22", "11-14", "12-13")), row.names = c(NA, -122L), class = c("tbl_df", "tbl", "data.frame"))
解决方案
核心思路是把所有MD列的月-日统一拼接成同一个基准年份的日期(选闰年比如2020,避免2月29日的兼容问题),这样既保留了具体日期的顺序,又能转换成Date类型用于绘图,最后修改X轴的刻度标签只显示月份。
步骤1:数据预处理
加载必要的包,将MD转换为带基准年份的Date:
library(tidyverse) library(lubridate) # 将MD列转换为2020年的日期(闰年,覆盖所有可能的月日) df <- df %>% mutate(day_of_year = ymd(paste("2020", MD, sep = "-")))
步骤2:绘制折线图
用ggplot绘制,按Year分组,X轴用转换后的day_of_year,设置刻度标签为月份:
ggplot(df, aes(x = day_of_year, y = thecount, color = Year, group = Year)) + geom_line() + geom_point() + # 设置X轴刻度为每个月的第一天,标签显示缩写月份 scale_x_date( breaks = seq(ymd("2020-01-01"), ymd("2020-12-01"), by = "month"), labels = ~ month(.x, label = TRUE), expand = c(0, 0) ) + labs( x = "月份", y = "计数", color = "年份", title = "各年份调查计数趋势" ) + theme_minimal()
关键说明
- 选择2020年作为基准是因为它是闰年,能处理所有可能的月日(包括2月29日)。
scale_x_date的breaks参数指定每个月第一天为刻度点,labels用month()函数只显示月份名称。group = Year确保每年的数据绘制为独立折线,不同年份的同日期点会自动对齐。
内容的提问来源于stack exchange,提问作者jschlener
相关产品推荐
相关产品推荐

