如何在ggplot中不转换日期格式将两年数据重叠绘制?
问题:ggplot两年周度数据重叠绘制与月份标签显示冲突
我用ggplot绘制两年的周度唯一数据(n),提取日期的周数作为x轴能实现两年数据重叠,但没法用scale_x_datetime显示月份标签;直接用date列绘制又没法让两年数据重叠,求解决办法。
能实现重叠但无月份标签的代码
data %>% mutate(week = week(date)) %>% ggplot() + geom_area(data = . %>% filter(year(date)==2022), aes(x = week, y = n), fill = 'grey70', alpha=0.2) + geom_line(data = . %>% filter(year(date)==2023), mapping = aes(x = week, y = n), color = "#02ACDC")
尝试显示月份标签但无法重叠的代码
data %>% mutate(year=year(date)) %>% ggplot(group=year) + geom_area(data = . %>% filter(year==2022), aes(x=date, y=n), fill='grey70', alpha=0.2) + geom_line(data = . %>% filter(year==2023), mapping = aes(x=date, y=n), color = "#02ACDC")+ scale_x_datetime(labels = date_format("%b"))
可复现数据
data <- structure(list(date = structure(c(1641081600, 1641686400, 1642291200, 1642896000, 1643500800, 1644105600, 1644710400, 1645315200, 1645920000, 1646524800, 1647129600, 1647734400, 1648339200, 1648944000, 1649548800, 1650153600, 1650758400, 1651363200, 1651968000, 1652572800, 1653177600, 1653782400, 1654387200, 1654992000, 1655596800, 1656201600, 1656806400, 1657411200, 1658016000, 1658620800, 1659225600, 1659830400, 1660435200, 1661040000, 1661644800, 1662249600, 1662854400, 1663459200, 1664064000, 1664668800, 1665273600, 1665878400, 1666483200, 1667088000, 1667692800, 1668297600, 1668902400, 1669507200, 1670112000, 1670716800, 1671321600, 1671926400, 1672531200, 1673136000, 1673740800, 1674345600, 1674950400, 1675555200, 1676160000, 1676764800, 1677369600, 1677974400, 1678579200, 1679184000), tzone = "UTC", class = c("POSIXct", "POSIXt")), n = c(64L, 419L, 560L, 450L, 386L, 316L, 418L, 351L, 311L, 478L, 253L, 298L, 215L, 169L, 134L, 115L, 176L, 121L, 132L, 135L, 148L, 118L, 135L, 203L, 120L, 137L, 100L, 101L, 87L, 94L, 94L, 177L, 132L, 70L, 127L, 92L, 226L, 234L, 519L, 657L, 545L, 487L, 710L, 471L, 336L, 380L, 396L, 354L, 340L, 190L, 139L, 52L, 74L, 479L, 587L, 390L, 624L, 750L, 816L, 682L, 371L, 368L, 236L, 39L)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -64L), groups = structure(list( date = structure(c(1641081600, 1641686400, 1642291200, 1642896000, 1643500800, 1644105600, 1644710400, 1645315200, 1645920000, 1646524800, 1647129600, 1647734400, 1648339200, 1648944000, 1649548800, 1650153600, 1650758400, 1651363200, 1651968000, 1652572800, 1653177600, 1653782400, 1654387200, 1654992000, 1655596800, 1656201600, 1656806400, 1657411200, 1658016000, 1658620800, 1659225600, 1659830400, 1660435200, 1661040000, 1661644800, 1662249600, 1662854400, 1663459200, 1664064000, 1664668800, 1665273600, 1665878400, 1666483200, 1667088000, 1667692800, 1668297600, 1668902400, 1669507200, 1670112000, 1670716800, 1671321600, 1671926400, 1672531200, 1673136000, 1673740800, 1674345600, 1674950400, 1675555200, 1676160000, 1676764800, 1677369600, 1677974400, 1678579200, 1679184000), tzone = "UTC", class = c("POSIXct", "POSIXt")), .rows = structure(list( 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L, 28L, 29L, 30L, 31L, 32L, 33L, 34L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 50L, 51L, 52L, 53L, 54L, 55L, 56L, 57L, 58L, 59L, 60L, 61L, 62L, 63L, 64L), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -64L), .drop = TRUE))
解决方案
直接用原date列无法重叠的原因是:两年的日期是实际不同年份的时间,x轴会按真实时间顺序排列,自然不会重叠。要同时实现数据重叠和月份标签显示,需将两年的日期映射到同一年(比如统一为2022年),这样x轴时间范围一致,且仍能被scale_x_datetime识别。
代码实现
library(lubridate) library(ggplot2) # 处理数据:将所有年份的日期映射到2022年对应月日 data_processed <- data %>% ungroup() %>% # 取消原数据分组,避免后续操作报错 mutate( year = year(date), # 生成映射后的同一年日期 mapped_date = ymd(paste(2022, month(date), day(date), sep = "-")) ) # 绘制图形 ggplot(data_processed) + geom_area(data = . %>% filter(year == 2022), aes(x = mapped_date, y = n), fill = 'grey70', alpha = 0.2) + geom_line(data = . %>% filter(year == 2023), aes(x = mapped_date, y = n), color = "#02ACDC") + scale_x_datetime(labels = scales::date_format("%b"), breaks = scales::date_breaks("1 month")) + labs(x = "月份")
关键说明
ungroup():取消原数据的分组结构,避免mutate操作时出现分组限制问题mapped_date:将所有日期的年份替换为2022,保证两年同一周的数据在x轴同一位置对齐scale_x_datetime:可正常识别mapped_date这个日期类型列,设置月份标签和间隔
内容的提问来源于stack exchange,提问作者adajam
相关产品推荐
相关产品推荐

