此问题以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个不同阴影区域的情节:
有3个部分遮挡不是太糟糕,但如果我需要遮阴100怎么办?有没有办法不定义100个数据帧,然后逐个添加所有这些阴影?
其次,我希望我的阴影超出价值的中间位置。但是,在所有三个规范(rect1
,rect2
和rect3
)中,每个着色都从该日期的值开始,并以下一个日期的值结束。关于如何做到这一点的任何提示?
答案 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)
结果图片:
要注意事项:
xmin = from - 1
移动左边界,使阴影矩形在from
列中指定的日期之前开始。rect
重命名为dateRanges
,以表明您可以将矩形数据从任何数据框中拉出来 - 它不必非常紧密与您将要执行的情节相关联(如果您更具描述性地命名数据框,则可能更容易跟踪线条。)ymin
和ymax
列,因为您可以直接引用-Inf
和Inf
。 我发现,如果您不需要可变宽度范围,实际上您可以只为数据框使用一列(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