ggplot:按月在同一个图上的多个时间段
Posted
技术标签:
【中文标题】ggplot:按月在同一个图上的多个时间段【英文标题】:ggplot: multiple time periods on same plot by month 【发布时间】:2022-01-12 21:52:49 【问题描述】:我试图在同一个时间序列图上按月绘制多个时间段。这是我的数据:https://pastebin.com/458t2YLg。我试图避免使用dput()
示例,但我认为减少样本并仍保留原始数据的结构会造成混乱。这里基本上是它的外观:
date fl_all_cumsum
671 2015-11-02 0.785000
672 2015-11-03 1.046667
673 2015-11-04 1.046667
674 2015-11-05 1.099000
675 2015-11-06 1.099000
676 2015-11-07 1.099000
677 2015-11-08 1.151333
基本上,它是跨越数年的每日数据。我的目标是比较几个冬季的累积雪滑翔(fl_all_cumsum
)(
与此非常相似:ggplot: Multiple years on same plot by month 但是,有一些区别,例如:1)时间段不是年份而是冬季(1.10.xxxx - 6.30.xxxx+1); 2)因为我只关心冬季,所以我希望 x 轴只从 10 月到次年 6 月底; 3) 数据不一致(几个月内有很多 NA 差距)。
我设法制作了这个:
library(zoo)
library(lubridate)
library(ggplot2)
library(scales)
library(patchwork)
library(dplyr)
library(data.table)
startTime <- as.Date("2016-10-01")
endTime <- as.Date("2017-06-30")
start_end <- c(startTime,endTime)
ggplot(data = master_dataset, aes(x = date, y = fl_all_cumsum))+
geom_line(size = 1, na.rm=TRUE)+
ggtitle("Cumulative Seasonal Gliding Distance")+
labs(color = "")+
xlab("Month")+
ylab("Accumulated Distance [mm]")+
scale_x_date(limits=start_end,breaks=date_breaks("1 month"),labels=date_format("%d %b"))+
theme(axis.text.x = element_text(angle = 50, size = 10 , vjust = 0.5),
axis.text.y = element_text(size = 10, vjust = 0.5),
panel.background = element_rect(fill = "gray100"),
plot.background = element_rect(fill = "gray100"),
panel.grid.major = element_line(colour = "lightblue"),
plot.margin = unit(c(1, 1, 1, 1), "cm"),
plot.title = element_text(hjust = 0.5, size = 22))
这实际上在视觉上效果很好,因为 x 轴根据需要从 10 月到 6 月;但是,我通过设置限制来做到这一点,
startTime <- as.Date("2016-10-01")
endTime <- as.Date("2017-06-30")
start_end <- c(startTime,endTime)
然后设置 1 个月的休息时间。
scale_x_date(limits=start_end,breaks=date_breaks("1 month"),labels=date_format("%d %b"))+
不用说,如果我想包括其他冬季和传奇,这种技术将不起作用。
我还尝试将季节分配给某些时间段,然后将它们用作一个因素:
master_dataset <- master_dataset %>%
mutate(season = case_when(date>=as.Date('2015-11-02')&date<=as.Date('2016-06-30')~"season 2015-16",
date>=as.Date('2016-11-02')&date<=as.Date('2017-06-30')~"season 2016-17",
date>=as.Date('2017-10-13')&date<=as.Date('2018-06-30')~"season 2017-18",
date>=as.Date('2018-10-18')&date<=as.Date('2019-06-30')~"season 2018-19"))
ggplot(master_dataset, aes(month(date, label=TRUE, abbr=TRUE), fl_all_cumsum, group=factor(season),colour=factor(season)))+
geom_line()+
labs(x="Month", colour="Season")+
theme_classic()
如您所见,我设法将其他季节包括在图表中,但现在有几个问题:
-
按月分组,它汇总了每日值,我在图表中丢失了每日动态(看看它是如何基于每月步骤的)
x 轴按时间顺序排列,这弄乱了我的可视化(请记住,我关心冬季的发展,所以我需要 x 轴从 10 月到 6 月底;请参阅我制作的第一张图表)李>
问题不大,但由于数据存在 NA 差距,因此图例还显示了“NA”因子
我不是程序员,所以我无法思考如何为此类问题编写代码。在一个完美的世界里,我想要像我制作的第一张图表一样,但包括所有冬季和一个传奇。有人对此有解决方案吗?提前致谢。
佐林
【问题讨论】:
【参考方案1】:这确实有点痛苦,而且相当繁琐。我创建了与您的 date
列相同的“假日期”,但年份设置为 2015/2016(使用 2016 作为 2 月份的日期,因此不会丢失闰日)。然后我们绘制所有数据,告诉 ggplot 都是 2015-2016,所以它被绘制在同一轴上,但我们没有标注年份。 (使用季节标签,并非“假”。)
## Configure some constants:
start_month = 10 # first month on x-axis
end_month = 6 # last month on x-axis
fake_year_start = 2015 # year we'll use for start_month-December
fake_year_end = fake_year_start + 1 # year we'll use for January-end_month
fake_limits = c( # x-axis limits for plot
ymd(paste(fake_year_start, start_month, "01", sep = "-")),
ceiling_date(ymd(paste(fake_year_end, end_month, "01", sep = "-")), unit = "month")
)
df = df %>%
mutate(
## add (real) year and month columns
year = year(date),
month = month(date),
## add the year for the season start and end
season_start = ifelse(month >= start_month, year, year - 1),
season_end = season_start + 1,
## create season label
season = paste(season_start, substr(season_end, 3, 4), sep = "-"),
## add the appropriate fake year
fake_year = ifelse(month >= start_month, fake_year_start, fake_year_end),
## make a fake_date that is the same as the real date
## except set all the years to the fake_year
fake_date = date,
fake_date = "year<-"(fake_date, fake_year)
) %>%
filter(
## drop irrelevant data
month >= start_month | month <= end_month,
!is.na(fl_all_cumsum)
)
ggplot(df, aes(x = fake_date, y = fl_all_cumsum, group = season,colour= season))+
geom_line()+
labs(x="Month", colour = "Season")+
scale_x_date(
limits = fake_limits,
breaks = scales::date_breaks("1 month"),
labels = scales::date_format("%d %b")
) +
theme_classic()
【讨论】:
谢谢。它完美无缺。不幸的是,我不得不花一些时间研究代码,因为乍一看我并不清楚你在这里做了什么类型的 wizzardy。 我会添加一些cmets。以上是关于ggplot:按月在同一个图上的多个时间段的主要内容,如果未能解决你的问题,请参考以下文章
android重复警报,应按月重复,每个月在同一天重复,依此类推