我试图在geom_rect()
中使用ggplot2
来遮蔽冬季,并且有许多不同的时间序列数据,其中包含不同的起点和终点。对于每个时间序列,我希望每年的11月到3月期间都要加上阴影(剩下的几个月不应该着色)。
例如,使用以下时间序列
library(ggplot2)
library(lubridate)
now <- Sys.time()
set.seed(123)
datOne <- data.frame(IndID = "One",
DateTime = seq(from = now - dyears(0.2), length.out = 50, by = "months"),
Value = rnorm(50))
我可以定义一个新的数据框对象,每个着色部分的起点和终点(即每年的11月 - 3月)
temp <- data.frame(
start = as.Date(c('2016-11-1', '2017-11-01', '2018-11-01', '2019-11-01')),
end = as.Date(c('2017-03-01', '2018-03-01', '2019-03-01', '2020-03-01')))
dateRanges <- data.frame(
start = as.POSIXct(temp [,1], "%Y-%m-%d")+ hours(6),
end = as.POSIXct(temp [,2], "%Y-%m-%d")+ hours(6))
然后制作一个情节。
ggplot(datOne) +
geom_rect(data = dateRanges, aes(xmin = start , xmax = end, ymin = -Inf, ymax = Inf),
inherit.aes=FALSE, alpha = 0.4, fill = c("lightblue"))+
geom_line(aes(x= DateTime, y = Value), size = 1.5)
虽然这适用于单个时间序列,但我为每个单独的时间序列制作一个单独的数字,每个时间序列都有不同的起点和终点,并且需要一个独特的数据框来创建着色区域。
例如,如下图所示,应用于不同时间序列的相同dateRanges
数据框显然不起作用。
datTwo <- data.frame(IndID = "Two",
DateTime = seq(from = now , length.out = 100, by = "months"),
Value = rnorm(100))
ggplot(datTwo) +
geom_rect(data = dateRanges, aes(xmin = start , xmax = end, ymin = -Inf, ymax = Inf),
inherit.aes=FALSE, alpha = 0.4, fill = c("lightblue"))+
geom_line(aes(x= DateTime, y = Value), size = 1.5)
是否有不同的方式来遮蔽两个时间序列,以便每个时间我可以自动创建dateRanges
或一起使用不同的方法(即注释...)。换句话说,鉴于需要在不同的时期内制作大约100个不同的数字和100个不同的时间序列,那么从11月到3月对任何一年的时间进行着色的最佳方法是什么?
提前致谢。
答案 0 :(得分:2)
我不知道这是否是“最好的”方法,但这很容易:展开dateRanges
框架并重置轴的限制:
# let's make it past & future proof for the next few years:
dateRanges <- data.frame(
start = seq(as.POSIXct("1900-11-01 07:00:00"), as.POSIXct("2100-11-01 07:00:00"), "1 year"),
end = seq(as.POSIXct("1901-03-01 07:00:00"), as.POSIXct("2101-03-01 07:00:00"), "1 year")
)
ggplot(datTwo) +
geom_rect(data = dateRanges, aes(xmin = start , xmax = end, ymin = -Inf, ymax = Inf),
inherit.aes=FALSE, alpha = 0.4, fill = c("lightblue"))+
geom_line(aes(x= DateTime, y = Value), size = 1.5) +
coord_cartesian(xlim = range(datTwo$DateTime))
答案 1 :(得分:2)
试试这个:
# make it a function
get.date.ranges <- function(data) {
range.df <- NULL
for (year in seq(min(year(data$DateTime)), year(max(data$DateTime)), 1)) {
cur <- data.frame(
start = as.POSIXct(as.Date(paste(year, '-11-1',sep='')), "%Y-%m-%d")+ hours(6),
end = as.POSIXct(as.Date(paste(year+1, '-03-1',sep='')), "%Y-%m-%d")+ hours(6)
)
if (cur$start <= max(data$DateTime)) {
range.df <- rbind(range.df, cur)
}
}
if (nrow(range.df) > 0) {
range.df[1,]$start <- max(range.df[1,]$start, min(data$DateTime))
range.df[nrow(range.df),]$end <- min(range.df[nrow(range.df),]$end, max(data$DateTime))
}
return(range.df)
}
# plot function
plot.data <- function(data) {
ggplot(data) +
geom_rect(data = get.date.ranges(data), aes(xmin = start , xmax = end, ymin = -Inf, ymax = Inf),
inherit.aes=FALSE, alpha = 0.4, fill = c("lightblue"))+
geom_line(aes(x= DateTime, y = Value), size = 1.5)
}
plot.data(datOne)
plot.data(datTwo)