R 使用ggplot绘制具有不同起点和终点的时间序列数据时的着色月间隔

R 使用ggplot绘制具有不同起点和终点的时间序列数据时的着色月间隔,r,ggplot2,lubridate,R,Ggplot2,Lubridate,我正在尝试使用ggplot2中的geom_rect()为冬季月份遮荫,并且有许多不同的时间序列数据,具有不同的起点和终点。对于每个时间序列,我希望从每年的11月到3月这段时间被着色(剩下的几个月应该不着色) 例如,使用以下时间序列 library(ggplot2) library(lubridate) now <- Sys.time() set.seed(123) datOne <- data.frame(IndID = "One", D

我正在尝试使用
ggplot2
中的
geom_rect()
为冬季月份遮荫,并且有许多不同的时间序列数据,具有不同的起点和终点。对于每个时间序列,我希望从每年的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))

虽然这适用于单个时间序列,但我正在为每个单独的时间序列制作一个单独的图形,每个时间序列都有不同的起点和终点,并且需要一个唯一的数据帧来创建着色区域。 例如,如下图所示,应用于不同时间序列的相同
日期范围
数据帧显然不起作用

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)
datwo我不知道这是否是“最好”的方法,但这是一个简单的方法:扩展您的
日期范围
帧并重置轴的限制:

# 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))
#让我们在接下来的几年里证明这一点:
dateRanges试试这个:

# 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)

# 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))
# 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)