在ggplot2中,如何避免geom_rect扩展情节的限制?

时间:2017-09-15 12:53:01

标签: r plot ggplot2

enter image description here

使用附加的代码段,geom_rect扩展了绘图的限制,即,即使该间隔中不包含任何数据,也会绘制2016年的垂直带。

我希望只有在包含数据点的情况下才能绘制矩形。

我阅读了annotate的帮助,并明确指出annotate完全符合geom_rect所见的行为,我希望避免这种行为。

  

详情

     

请注意,所有位置美学都会缩放(即它们会扩展   情节的界限,因此它们是可见的),但所有其他美学   已设定。这意味着使用此功能创建的图层永远不会   影响传奇。

library(ggplot2)
days<-rep(Sys.Date(),100)+seq(1,100)
v<-sin(as.numeric(days))
df<-data.frame(days=c(days,days),v=c(v,cos(v)+.1),n=c(rep('a',100),rep('b',100)))

shade <- data.frame(x1=c(as.Date('2016-10-15'),as.Date('2017-11-11')), 
                    x2=c(as.Date('2016-10-20'),as.Date('2017-11-13')), 
                    y1=c(-Inf,-Inf), y2=c(Inf,Inf))

plot(ggplot(df, aes(x=days, y=v, colour=n)) +
  geom_line() +
  geom_rect(data=shade, inherit.aes = F,
            aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), 
            color = 'grey', alpha=0.2) +
  geom_point())

3 个答案:

答案 0 :(得分:2)

根据range(df$days)设置限制是否适用于您的情况?

my_limits <- range(df$days)

ggplot(df, aes(x=days, y=v, colour=n)) +
    geom_line() +
    geom_rect(data=shade, inherit.aes = F,
           aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), 
           color = 'grey', alpha=0.2) +
    geom_point() +
    scale_x_date(limits = my_limits) # See scale_x_datetime in case the data has time too.

enter image description here

答案 1 :(得分:1)

我的解决方案创建矩形图并将其添加到主图中daysshade的区间内。使用lubridate包执行日期操作。

# Main plot that doesn't change depending on time interval
pMain <- ggplot(df, aes(days, v, colour = n)) +
    geom_line() +
    geom_point()

# Time manipulation part
library(lubridate)
# Turn character string to dates
df$days <- ymd(df$days)
shade$x1 <- ymd(shade$x1)
shade$x2 <- ymd(shade$x2)

# Check which shade entries contain days 
foo <- c()
for(i in nrow(shade)) {
    bar <- any(df$days %within% interval(shade[i, ]$x1, shade[i, ]$x2))
    if (bar) {
        foo <- c(foo, i)
    }
}

# If any interval contained days
# Create rectangle plot and add it to the main plot
CONTAINS <- length(foo) > 0
if (CONTAINS) {
    pRect <-  geom_rect(data=shade[foo, ], inherit.aes = F,
                aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), 
                color = 'grey', alpha=0.2)
    pMain <- pMain + pRect
}
plot(pMain)

enter image description here

答案 2 :(得分:1)

在将其提供给ggplot:

之前,只需过滤shade
library(dplyr)
library(ggplot2)
days<-rep(Sys.Date(),100)+seq(1,100)
v<-sin(as.numeric(days))
df<-data.frame(days=c(days,days),v=c(v,cos(v)+.1),n=c(rep('a',100),rep('b',100)))

shade <- data.frame(x1=c(as.Date('2016-10-15'),as.Date('2017-11-11')), 
                    x2=c(as.Date('2016-10-20'),as.Date('2017-11-13')), 
                    y1=c(-Inf,-Inf), y2=c(Inf,Inf)) %>%
  filter(between(x1, min(df$days), max(df$days)), between(x2, min(df$days), max(df$days)))

plot(ggplot(df, aes(x=days, y=v, colour=n)) +
       geom_line() +
       geom_rect(data=shade, inherit.aes = F,
                 aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), 
                 color = 'grey', alpha=0.2) +
       geom_point())