Color the areas between two lines using geom_ribbon did not work as expected

I wanted to color the region between the min and the max lines for NoChange and WithChange group but somehow managed to color more than I needed to.
Can anyone show me where it went wrong? Thank you

library(tidyverse)

dat <- data.frame(
  stringsAsFactors = FALSE,
  Year = c(2010,2010,2010,2030,2030,2030,
           2010,2010,2010,2030,2030,2030),
  Solution = c("NoChange","NoChange","NoChange",
               "NoChange","NoChange","NoChange",
               "WithChange","WithChange","WithChange",
               "WithChange","WithChange",
               "WithChange"),
  Level = c("NoChange_Max","NoChange_Min",
            "NoChange_Avg","NoChange_Max",
            "NoChange_Min","NoChange_Avg","WithChange_Max",
            "WithChange_Min","WithChange_Avg",
            "WithChange_Max","WithChange_Min",
            "WithChange_Avg"),
  Price = c(19,19,19,36,19,24,19,19,19,
            69,50,63)
)
dat
#>    Year   Solution          Level Price
#> 1  2010   NoChange   NoChange_Max    19
#> 2  2010   NoChange   NoChange_Min    19
#> 3  2010   NoChange   NoChange_Avg    19
#> 4  2030   NoChange   NoChange_Max    36
#> 5  2030   NoChange   NoChange_Min    19
#> 6  2030   NoChange   NoChange_Avg    24
#> 7  2010 WithChange WithChange_Max    19
#> 8  2010 WithChange WithChange_Min    19
#> 9  2010 WithChange WithChange_Avg    19
#> 10 2030 WithChange WithChange_Max    69
#> 11 2030 WithChange WithChange_Min    50
#> 12 2030 WithChange WithChange_Avg    63

Create the Min and Max columns

dat <- dat %>%
  group_by(Level) %>%
  mutate(Min = min(Price, na.rm = TRUE),
         Max = max(Price, na.rm = TRUE))

price_change1 <- ggplot(dat %>% filter(!str_detect(Level, "Avg")),
                        aes(x = Year, y = Price, color = Level)) +
  geom_line(size = 0.75)
price_change1

price_change2 <- price_change1 +
  geom_ribbon(data = dat %>% filter(Level != "NoChange_Avg") %>% filter(Solution == "NoChange"),
              aes(x = Year, ymin = Min, ymax = Max),
              inherit.aes = FALSE,
              fill = "darkblue", alpha = 0.5) +
  geom_ribbon(data = dat %>% filter(Level != "NoChange_Avg") %>% filter(Solution == "WithChange"),
              aes(x = Year, ymin = Min, ymax = Max),
              inherit.aes = FALSE,
              fill = "turquoise", alpha = 0.5)
price_change2

You need to group by Solution and Year, not Level. Your Level is already divided by min and max, so you won't get both in a group.

dat <- dat %>%
  group_by(Solution, Year) %>%
  mutate(Min = min(Price, na.rm = TRUE),
         Max = max(Price, na.rm = TRUE))

Changing that gave me this graph:

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.