如何在 ggplot2 中自动突出显示 x 轴的多个部分?

How can I automatically highlight multiple sections of the x axis in ggplot2?

我有一个线图可以跟踪多个因素随时间的变化。我正在使用的数据的模拟版本是:

step   factor   count
1      a        10
1      b        0
1      c        5
2      a        5
2      b        10
2      c        0
... etc.

计数受外部事件的影响,对于每一步,我都知道该事件是否正在发生。这些信息可以在不同的数据帧中,也可以在同一个数据帧中,这并不重要,它看起来像这样:

step   event
1      FALSE
2      FALSE
...
10     TRUE
11     TRUE
...
30     FALSE
... etc.

我正在编写这个脚本来自动创建绘图,因为我将处理大量数据,虽然我知道我可以使用 geom_rect() 来硬编码突出显示的矩形,但绝对不行我可以在不浪费太多时间的情况下手动执行某些操作,尤其是考虑到事件可以在不同情况下以不同步骤打开和关闭。

有什么方法可以从数据中动态提取 geom_rect() 的 x 限制,并根据数据集的需要创建尽可能多的矩形?或者这完全没有希望了?

这可能有点老套,但我认为它给出了您正在寻找的结果。让我先创建一些与您大致对应的数据:

df <- data.frame(step = rep(1:100, 3), group = rep(letters[1:3], each = 100),
                 value = c(cumsum(c(50, runif(99, -1, 1))), 
                           cumsum(c(50, runif(99, -1, 1))),
                           cumsum(c(50, runif(99, -1, 1)))))

df2 <- data.frame(step = 1:100, event = sample(c(TRUE, FALSE), 100, TRUE))

所以 df 的起始情节应该是这样的:

ggplot(df, aes(step, value, colour = group)) + geom_line()

事件数据框如下所示:

head(df2)
#>   step event
#> 1    1 FALSE
#> 2    2 FALSE
#> 3    3 FALSE
#> 4    4  TRUE
#> 5    5 FALSE
#> 6    6  TRUE

我们的想法是在图中添加半透明的红色 geom_area,使 FALSE 值远低于范围底部,TRUE 值远高于顶部的范围,然后只需设置 coord_cartersian 以便 y 限制接近您的主要数据的限制。只要你的事件是 TRUE:

,这就会给你红色垂直带
ggplot(df, aes(step, value, colour = group)) + 
  geom_line() + 
  geom_area(data = df2, aes(x = step, y = 1000 * event), 
            inherit.aes = FALSE, fill = "red", alpha = 0.2) + 
  coord_cartesian(ylim = c(40, 60)

这是@Allan 优秀方法的另一种方法,它依赖于将事件数据预处理成具有 dplyr 的组:

library(dplyr)
data2 %>% 
  group_by(group = cumsum(c(1,diff(event))!=0)) %>%
  dplyr::filter(event == TRUE & (step == min(step) | step == max(step))) %>%
ggplot() +
  geom_ribbon(aes(x = step, group = group, ymax = Inf, ymin = -Inf), 
              fill = "yellow", alpha = 0.3) +
  geom_line(data = data, aes(x = step, y = count, color = factor)) +
  facet_wrap(.~factor, ncol = 1)

set.seed(3)  
data <- data.frame(step = rep(1:30, each = 3), factor = rep(letters[1:3],times = 30), count = round(runif(90,0,100)))
data2 <- data.frame(step = 1:30, event = rep(c(TRUE,FALSE,TRUE,FALSE,TRUE,FALSE), c(3,7,2,8,4,6)))
data2
   step event
#1     1  TRUE
#2     2  TRUE
#3     3  TRUE
#...
#28   28 FALSE
#29   29 FALSE
#30   30 FALSE