在ggplot2中着色许多不同的部分

时间:2014-12-04 23:04:01

标签: r plot ggplot2

此问题以How can i provide shades between dates on x axis in R plot?How to align multiple ggplot2 plots and add shadows over all of them为基础。

在进入细节之前,我希望能够压缩我必须编写的代码量,以便遮蔽许多不同的部分。我希望能够将所有这些信息整合到一段代码中。

这是我的MWE:

library(ggplot2)
library(scales)
set.seed(1)
data <- data.frame(Date = seq(as.Date('2000-01-01'), 
                   len= 23, by="1 day"), 
                   Value = sample(1:50, 23, replace=TRUE))
rect1 <- data.frame(xmin=as.Date('2000-01-03 12:00:00'), 
                    xmax=as.Date('2000-01-04 12:00:00'), 
                    ymin=-Inf, 
                    ymax=Inf)
rect2 <- data.frame(xmin=as.Date('2000-01-10'), 
                    xmax=as.Date('2000-01-11'), 
                    ymin=-Inf, 
                    ymax=Inf)
rect3 <- data.frame(xmin=as.Date('2000-01-17 00:00:00'), 
                    xmax=as.Date('2000-01-18 00:00:00'), 
                    ymin=-Inf, 
                    ymax=Inf)
ggplot() + 
  geom_line(data=data, aes(x = Date, y = Value)) + 
  geom_rect(data = rect1, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha = 0.4) + 
  geom_rect(data = rect2, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha = 0.4) + 
  geom_rect(data = rect3, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax), alpha = 0.4) + 
  scale_x_date(breaks = date_breaks("1 day"), labels = date_format("%d"))

因此,我得到了一个有3个不同阴影区域的情节:

Plot of MWE

有3个部分遮挡不是太糟糕,但如果我需要遮阴100怎么办?有没有办法不定义100个数据帧,然后逐个添加所有这些阴影?

其次,我希望我的阴影超出价值的中间位置。但是,在所有三个规范(rect1rect2rect3)中,每个着色都从该日期的值开始,并以下一个日期的值结束。关于如何做到这一点的任何提示?

2 个答案:

答案 0 :(得分:3)

你比你想象的更近!

您可以只创建一个数据框,而不是为每个矩形创建一个数据框,其中每一行是要着色的日期范围。这是上面示例的单数据框版本(data与您的相同)。

dateRanges <- data.frame(
    from=as.Date(c('2000-01-03 12:00:00', '2000-01-10', '2000-01-17 00:00:00')), 
    to=as.Date(c('2000-01-04 12:00:00', '2000-01-11', '2000-01-18 00:00:00'))
)
ggplot() + geom_line(data=data, aes(x = Date, y = Value)) + 
    geom_rect(data = dateRanges, aes(xmin = from - 1, xmax = to, ymin = -Inf, ymax = Inf), alpha = 0.4)

结果图片:

plot with rectangles shaded

要注意事项:

  1. 使用xmin = from - 1移动左边界,使阴影矩形在from列中指定的日期之前开始。
  2. 我已将其从rect重命名为dateRanges,以表明您可以将矩形数据从任何数据框中拉出来 - 它不必非常紧密与您将要执行的情节相关联(如果您更具描述性地命名数据框,则可能更容易跟踪线条。)
  3. 同样在您的情况下,您不需要数据框中的yminymax列,因为您可以直接引用-InfInf
  4. 更新

    我发现,如果您不需要可变宽度范围,实际上您可以只为数据框使用一列(importantDates = data.frame(Date=as.Date(c(...)))),然后使用xmin = Date - 1, xmax =图中的日期+ 1`。

    此外,如果它适合您的情况,您甚至可以基于原始数据的一列或多列生成importantDates数据框,类似importantDates <- data[data$Value > 40,](或其他)。

答案 1 :(得分:1)

您可以使用POSIXct对象在中间绘制阴影。

您可以包含任意数量的阴影来定义包含所有坐标的列表。

library(ggplot2)
library(scales)
set.seed(1)
data <- data.frame(
  Date = as.POSIXct(seq(as.Date('2000-01-01'), len= 23, by="1 day")), 
  Value = sample(1:50, 23, replace=TRUE)
)

您可以定义一个包含所有日期的向量,假设带宽始终为一天。或者,您可以定义包含两个日期的数据框,并使用apply或dlply(来自plyr)。

vectorDates <-seq(
  as.POSIXct('2000-01-03 12:00:00'),
  as.POSIXct('2000-01-20 12:00:00'),
  length.out = 10
)
list_geom_rect <- lapply(vectorDates, function(date1)
{
  date2 <- date1 + 3600 * 24
  rect <- data.frame(
    xmin = date1, xmax = date2, 
    ymin = -Inf,  ymax = Inf
  )
  geom_rect(
    data = rect,
    mapping = aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
    alpha = 0.4
  )
})

现在您可以构建绘图并添加所有波段。

 p <- ggplot() + geom_line(data=data, aes(x = Date, y = Value))
    for(geom in list_geom_rect){
      p <- p + geom
    }
 p