dhruvak_a
dhruvak_a

Reputation: 41

Conditionally change background colour of line plot in ggplot2

I have a dataset that looks like this:

Date <- seq(as.Date("2018-01-01"),as.Date("2021-01-01"),by="days")
quant <- runif(1097,1000,6000)
cost <- runif(1097,2.5,6.0)
price <- runif(1097,2.5,6.0)
df <- data.frame(Date,quant,cost,price)

I want to construct a plot in which has "cost" and "price" are two separate lines, and wherever price > cost, the background of the plot is a different colour. The closest plot to this that I found is this: plot

The difference is that the above plot has only one line, while I need two lines based on two different variables. I also prefer controlling the background color so that wherever price <= cost, the background colour is the default grey, while wherever price > cost, the background is a light shade of some colour.

Thanks.

Upvotes: 1

Views: 346

Answers (2)

Leonardo
Leonardo

Reputation: 2485

for better visualization I think it is better to use a random walk rather than a set of uniform random numbers.

I propose a solution that can be improved (for example by placing the background in transparency and arranging margins)

# generates random walk function
random_walk <- function(p, lower, upper) {
  values <- c()
  current <- 0
  for (i in 1:1097) {
    if (current == lower) {
      current <- current + 0.1
      values <- c(values, current)
    } else if (current == upper) {
      current <- current - 0.1
      values <- c(values, current)
    } else {
      current <- current + ifelse(runif(1) < p, 0.1, -0.1)
      values <- c(values, current)
    }
  }
  return(values)
}
# generate two random walks
r_cost <- random_walk(0.51, 2.5, 6.0)
r_price <- random_walk(0.51, 2.5, 6.0)
r_bg <- ifelse(r_cost <= r_price, "a", "b")

# generate date and df
Date <- seq(as.Date("2018-01-01"),as.Date("2021-01-01"),by="days")
df <- data.frame(Date, cost = r_cost, price = r_price, bg = r_bg)

# plot
ggplot(df, aes(x = Date)) + 
  geom_rect(aes(xmin = Date, xmax = Date,
                ymin = -Inf, ymax = Inf,
                color = bg),
            show.legend = FALSE) +
  scale_color_manual(values = c("grey60", "grey70")) +
  geom_line(aes(y = cost), color = "steelblue4", size = 0.25) + 
  geom_line(aes(y = price), color = "firebrick2", size = 0.25)

Upvotes: 1

Duck
Duck

Reputation: 39585

Try this, rehaping data and hacking colors after creating a variable:

library(dplyr)
library(ggplot2)
library(tidyr)
#Code
df %>%
  mutate(Val=+(price>cost)) %>%
  pivot_longer(-c(Date,Val)) %>%
  filter(name!='quant') %>%
  ggplot(aes(x=Date,y=value))+
  geom_bar(stat='identity',aes(x=Date,y=6,fill=factor(Val)),
           position = position_dodge(0.9),alpha=0.1,show.legend = F)+
  geom_line(aes(color=name))+
  scale_fill_manual(values=c('0'='transparent','1'='magenta'))+
  labs(color='variable')

Output:

enter image description here

Upvotes: 0

Related Questions