Home > OS >  Shade parts of a ggplot based on a (changing) dummy variable
Shade parts of a ggplot based on a (changing) dummy variable

Time:09-17

I want to shade areas in a ggplot but I don't want to manually tell geom_rect() where to stop and where to start. My data changes and I always want to shade several areas based on a condition.

Here for example with the condition "negative":

library("ggplot2")
set.seed(3)
plotdata <- data.frame(somevalue = rnorm(10), indicator = 0 , counter = 1:10)
plotdata[plotdata$somevalue < 0,]$indicator <- 1
plotdata

I can do that manually like here or here:

plotranges <- data.frame(from = c(1,4,9),  to = c(2,4,9))
ggplot()   
geom_line(data = plotdata, aes(x = counter, y = somevalue))  
geom_rect(data = plotranges, aes(xmin = from - 1, xmax = to, ymin = -Inf, ymax = Inf), alpha = 0.4)

But my problem is that, so to speak, the set.seed() argument changes and I want to still automatically generate the plot without specifying min and max values of the shading manually. Is there a way (maybe without geom_rect() but instead geom_bar()?) to plot shading based directly on my indicator variable?

edit: Here is my own best attempt, as you can see not great:

ggplot(data = plotdata, aes(x = counter, y = somevalue))   geom_line()   
 geom_bar(aes(y = indicator*max(somevalue)), stat= "identity")

CodePudding user response:

You can use stat_summary() to calculate the extremes of runs of your indicator. In the code below data.table::rleid() groups the data by runs of indicators. In the summary layer, y doesn't really do anything, so we use it to store the resolution of your datapoints, which we then later use to offset the xmin/xmax parameters. The after_stat() function is used to access computed variables after the ranges have been computed.

library("ggplot2")

plotdata <- data.frame(somevalue = rnorm(10), counter = 1:10)
plotdata$indicator <- as.numeric(plotdata$somevalue < 0)

ggplot(plotdata, aes(counter, somevalue))  
  stat_summary(
    geom = "rect",
    aes(group = data.table::rleid(indicator),
        xmin = after_stat(xmin - y * 0.5),
        xmax = after_stat(xmax   y * 0.5),
        alpha = I((indicator) * 0.4),
        y = resolution(counter)),
    fun.min = min, fun.max = max,
    orientation = "y", ymin = -Inf, ymax = Inf
  )  
  geom_line()

Created on 2021-09-14 by the reprex package (v2.0.1)

  • Related