Search code examples
rggplot2timelubridategeom-area

How to stack partially matched time periods with geom_area (ggplot2)?


With the following example, I get a plot where the areas are not stacked. I would like to stack them. This should be a partial stack, intensity starting at 0.5, then reaching 0.8 where stacked, then reaching 0.3 at the end.

I assume that the position argument does not work as the start and end date are not the same.

  1. Am I missing an argument that could solve this issue? Or maybe another geom?
  2. Do I have to subset the data into days, to get the desired output. If so, how can I acheive that?

Thanks in advance,

# Library
library(tidyverse)
library(lubridate)

# Data
df <- tibble(date_debut = as_date(c("2022-09-28", "2022-10-05")),
       intensity = c(0.5, 0.3),
       duration = days(c(14, 10)),
       type = (c("a", "b")))

# Adjustment
df <- df %>%
  mutate(date_fin = date_debut + duration) %>%
  pivot_longer(cols = c(date_debut, date_fin),
               names_to = "date_type",
               values_to = "date") 

# Plot
df %>%
  ggplot(aes(x = date, y = intensity, fill = type))+
  geom_area(position = "stack")

Solution

  • This is a tough data wrangling problem. The area plots only stack where the points in the two series have the same x values. The following will achieve that, though it's quite a profligate approach.

    df %>%
      mutate(interval = interval(date_debut, date_debut + duration)) %>%
      group_by(type) %>%
      summarize(time = seq(as.POSIXct(min(df$date_debut)), 
                           as.POSIXct(max(df$date_debut + df$duration)), by = 'min'),
                intensity = ifelse(time %within% interval, intensity, 0)) %>%
      ggplot(aes(x = time, y = intensity, fill = type)) +
      geom_area(position = position_stack())
    

    enter image description here