Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill background of ggplot conditionally in R

Tags:

r

ggplot2

I would like to fill the background of a ggplot in R with a specific color.

The dataframe contains 3 columns: time, value, and color.

df <- data.frame(time = seq(1, 100, 1), 
                 value = c(runif(n = 45, min = 1, max= 10), runif(10, 40, 50), runif(45, 70, 90)), 
                 color = c(rep("green", 45), rep("orange", 10), rep("red", 45))) 

I am able to fill background of the plot in the following manner:

library(tidyverse)

ggplot(df) + 
  geom_line(aes(x = time, y = value)) + 
  annotate("rect", xmin=-Inf, xmax= 45, ymin = -Inf, ymax = Inf, alpha = 0.2, fill = "green") +
  annotate("rect", xmin=45, xmax= 55, ymin = -Inf, ymax = Inf, alpha = 0.2, fill = "orange") +
  annotate("rect", xmin=55, xmax= Inf, ymin = -Inf, ymax = Inf, alpha = 0.2, fill = "red") 

enter image description here

Question

In the example above, the background fill is 'hard coded'. Is there a more convenient/automated way to find the xmin and xmax values of the borders between the color transitions?

like image 218
user213544 Avatar asked Sep 17 '25 17:09

user213544


2 Answers

You can layer a tile plot with just one row behind and use cut to assign a color to each point.

For your data, I could use a simple cut. But I doubt that it will always play out as nicely as with the example data:

ggplot(df) + 
  geom_tile(aes(x=time,y=50,fill=cut(value,3)),height=100,alpha=0.2) + 
  geom_line(aes(x=time,y=value))

enter image description here

Edit: I missed you already have the color in your data

Then it is even simpler:

ggplot(df) + 
  geom_tile(aes(x=time,y=50,fill=color),height=100,alpha=0.2) + 
  geom_line(aes(x=time,y=value)) + 
  scale_fill_manual("Important aspect", values=c("green","orange","red"))

enter image description here

like image 148
ziggystar Avatar answered Sep 19 '25 06:09

ziggystar


library(tidyverse)

# create a summary table to use for plotting positions
d = df %>%
  group_by(color) %>%
  summarise(maxtime = max(time))

# plot using you dataset (for the line)
# and the summary table for the color areas
ggplot(df) + 
  geom_line(aes(x = time, y = value))+
  geom_rect(data = data.frame(d$maxtime),
            xmin = lag(d$maxtime, default = -Inf), 
            xmax = d$maxtime,
            ymin = rep(-Inf, nrow(d)), 
            ymax = rep(Inf, nrow(d)),
            fill = d$color, 
            alpha = 0.2) 

Your summary table d shows you the x-axis positions where your color should change and what color that is. And it looks like:

# # A tibble: 3 x 2
#   color  maxtime
#   <fct>    <dbl>
# 1 green       45
# 2 orange      55
# 3 red        100

Then you have to find a way to use d and pass the appropriate info to function geom_rect

like image 43
AntoniosK Avatar answered Sep 19 '25 07:09

AntoniosK