CumSum over Time against Total in ggplot2

Viewed 155

Easiest way to explain is via this image:enter image description here

I would like to make a stacked ggplot which shows (in values, not percent) the cumulative sum of a value over time while simultaneously, the total "potential" for that value in the background.

I imagine the dataset would need to look something like:

+------------+-------+------------------+-----------------+
|    Date    | Value | Cumulative Value | Potential Value |
+------------+-------+------------------+-----------------+
| 2017-01-01 |   100 |              100 |             500 |
| 2018-01-01 |   100 |              200 |             500 |
| 2019-01-01 |   100 |              300 |             500 |
+------------+-------+------------------+-----------------+

#example set:
df <- data.frame(
"Date" = as.Date( c("2017-01-01","2018-01-01","2019-01-01") ), 
"Value" = c(100,100,100),
"Cumulative Value" = c(100,200,300), 
"Potential Value" = c(500,500,500)
)

My primary attempt was something along the lines of:

ggplot(df, aes(y=`Cumulative.Value`, x=Date)) +
     geom_bar( stat="identity")

And then I started reading into the position_stack option - Just a little confused on direction here.

1 Answers

Here's some slightly adjusted example data to make the shape clearer to see:

df <- data.frame(
  "Date" = as.Date( c("2017-01-01","2018-01-01","2019-01-01") ), 
  "Value" = c(100,150,100),
  "Cumulative Value" = c(100,250,350), 
  "Potential Value" = c(500,500,500)
)

One approach using geom_area + geom_ribbon:

ggplot(df, aes(y=`Cumulative.Value`, x=Date)) +
  geom_area() +
  geom_ribbon(aes(ymin = `Cumulative.Value`,
                  ymax = `Potential.Value`), fill = "gray80")

enter image description here

Or two geom_cols, the potential one behind:

ggplot(df, aes(y=`Cumulative.Value`, x=Date)) +
  geom_col(aes(y = Potential.Value), fill = "gray80") +
  geom_col( stat="identity")

enter image description here

Or use geom_rect, which will show regions between the known x values. Here I make up an end date 30 days later so that we can see the ending value. I plot the "Potential" one first so that if the Cumulative exceeds it, it will be plotted on top of it like in your example at the far right.

ggplot(df, aes(xmin = Date, 
               xmax = lead(Date, default = max(df$Date) + 30))) +
  geom_rect(aes(ymin = Cumulative.Value, ymax = Potential.Value), fill = "gray80") 
  geom_rect(aes(ymin = 0, ymax = Cumulative.Value)) +

enter image description here

Related