Hi there, I would like to make a plot with geom_area with different colours to negative and positive values, but I am getting an error that I could not find out how to solve with this specific data. I mean, I have found out there other examples that work, but not able to apply the logic to this data that comes from TidyTuesday.

Then, I'd like to positive and negative in different colors. I thought that creating the 'signal' variable and passing it into fill would resolve, but not.

dt.2 %>%
ggplot(aes(x = month, y = diff, fill = signal, group = 1))+
geom_area()

I got an error: "Erro: Aesthetics can not vary with a ribbon"

After some googling, I think that there is some natural limitation of the geom_ribbon() (and consequently geom_area()) that does not allow the desired behavior. This is somehow connected to the way how the actual color for each pixel is defined in ggplots. For instance, with the same data, if you try to plot a line with the same idea in mind you will get the following:

dt.2 %>%
ggplot(aes(x = month, y = diff, color = diff > 0, group = 1))+
geom_line()

As you may see, color changes, but not exactly where you want it to be.
In order to overcome this limitation, you can add extra points with y = 0 and x = 'position where the line intersects x-axis' and then break the whole plot into groups with its own color (in this specific case into 3 groups).

library(tidyverse)
library(tidytuesdayR)
tt <- tt_load("2021-03-16")
dt <- tt$games
dt.2 <- dt %>%
filter(year == 2020) %>%
mutate(month = fct_relevel(month, month.name)) %>%
group_by(year, month) %>%
summarise(diff = sum(gain, na.rm = T)) %>%
ungroup()
# Since months are discrete, while we need to define x coordinate
# somewhere between months, we need to convert factor to double
dt.plot <- dt.2 %>%
mutate(month = as.numeric(month))
# This banch of lines detects the position where diff changes sign
# and assign it to groups
dt.int1 <- dt.plot %>%
# Define the observation between which sign is changes
mutate(si = sign(diff),
delta = si - lead(si),
nex = lag(delta)) %>%
filter(abs(delta) == 2 | abs(nex) == 2) %>%
# Using some trigonometry calculate x-coordinate of transition
mutate(delta2 = abs(lead(diff)) + abs(diff),
month = month + abs(diff)/delta2) %>%
filter(abs(delta) == 2) %>%
add_tally() %>%
mutate(gr = 1:median(n),
diff = 0) %>%
select(-si, -delta, -nex, -delta2, -n)
# We need each y = 0 points at both groups ("positive" and "negative")
dt.int2 <- dt.int1 %>%
mutate(gr = gr+1)
# Now we adding y = 0 to original dataset
dt.plot <- bind_rows(dt.plot, dt.int1, dt.int2) %>%
arrange(month) %>%
# this need to assign each observation in original dataset to
# one of the gr's
fill(gr, .direction = "downup")
# As we need only two colors, but we have three groups
# we need to define additional variable for fill
dt.plot <- dt.plot %>%
group_by(gr) %>%
summarise(fll = mean(diff) > 0) %>%
full_join(dt.plot)
# Now we make a plot and re-defining x coordinates back to months
ggplot(dt.plot,
aes(month, diff, fill = factor(fll), group = gr))+
geom_area() +
scale_x_continuous(breaks = 1:12, labels = month.name)

Wow! Thank you so much! The result is perfect! But, it was more difficult than I thought to achieve it. I'm going to study your code to try to understand it better! Thank you, thank you, thank you!