Caner
Caner

Reputation: 678

How can we use multiple geom_smooth in a single chart?

I would like to use multiple geom_smooth layers in a single ggplot2 chart. When I try to do that, the color scheme gets screwed up. Here is an example demonstrating what is happening.

We construct a simple dataframe we want to visualize.

df = data.frame(x = c("a", "b", "c"),
             y1 = seq(1, 3),
             y1_upr = seq(2, 4),
             y1_lwr = seq(0, 2),
             y2 = seq(2, 4),
             y2_upr = seq(2.5, 4.5),
             y2_lwr = seq(1.5, 3.5))

We can visualize y1 and y2 easily.

plot_obj = ggplot(data = df, aes(x = x, group = 1)) + 
  geom_line(aes(y = y1, colour = "y1")) + 
  geom_line(aes(y = y2, colour = "y2")) +     
  scale_colour_manual("", breaks = c("y1", "y2"), values = c("blue", "red"))
plot_obj

enter image description here If we add one geom_smooth, the behavior is still as expected.

plot_obj + 
  geom_smooth(aes(y = y1, ymin = y1_lwr, ymax = y1_upr), stat="identity", fill="blue", alpha=0.2)

enter image description here Lastly, we add the second geom_smooth layer.

plot_obj + 
  geom_smooth(aes(y = y1, ymin = y1_lwr, ymax = y1_upr), stat="identity", fill="blue", alpha=0.2) + 
  geom_smooth(aes(y = y2, ymin = y2_lwr, ymax = y2_upr), stat="identity", fill="red", alpha=0.2)

enter image description here

Notice that the top line is no longer red in the last chart. Why is this happening and how can it be fixed? Thank you!

Upvotes: 1

Views: 23351

Answers (2)

aosmith
aosmith

Reputation: 36076

Certainly reshaping your dataset will make things easier, and is the recommended approach. However, if you want to keep using separate layers:

As you haven't mapped a color for geom_smooth, it uses the default color of blue for the smoothed lines it drew. If you want just the ribbon, use geom_ribbon instead.

ggplot(data = df, aes(x = x, group = 1)) + 
    geom_line(aes(y = y1, colour = "y1")) + 
    geom_line(aes(y = y2, colour = "y2")) +     
    scale_colour_manual("", breaks = c("y1", "y2"), values = c("blue", "red")) +
    geom_ribbon(aes(ymin = y1_lwr, ymax = y1_upr), stat="identity", fill="blue", alpha=0.2) + 
    geom_ribbon(aes(ymin = y2_lwr, ymax = y2_upr), stat="identity", fill="red", alpha=0.2)

enter image description here

Otherwise you'll need to map your colors for each smooth layer within aes or set them manually to red and blue or NA outside of aes.

ggplot(data = df, aes(x = x, group = 1)) + 
    geom_line(aes(y = y1, colour = "y1")) + 
    geom_line(aes(y = y2, colour = "y2")) +     
    scale_colour_manual("", breaks = c("y1", "y2"), values = c("blue", "red")) +
    geom_smooth(aes(y = y1, ymin = y1_lwr, ymax = y1_upr, colour = "y1"), 
              stat="identity", fill="blue", alpha=0.2) + 
    geom_smooth(aes(y = y2, ymin = y2_lwr, ymax = y2_upr, colour = "y2"), 
              stat="identity", fill="red", alpha=0.2)

enter image description here

Upvotes: 5

joran
joran

Reputation: 173577

I would probably do something closer to this:

library(dplyr)
df1 <- df %>%
    select(x,contains("y1")) %>%
    rename(y = y1, y_upr = y1_upr, y_lwr = y1_lwr) %>%
    mutate(grp = "y1")
df2 <- df %>%
    select(x,contains("y2")) %>%
    rename(y = y2, y_upr = y2_upr, y_lwr = y2_lwr) %>%
    mutate(grp = "y2")
df_all <- bind_rows(df1, df2)

ggplot(df_all,aes(x = x, y = y, ymin = y_lwr, ymax = y_upr, group = grp)) +
    geom_line(aes(color = grp)) + 
    geom_ribbon(aes(fill = grp), alpha = 0.2)

enter image description here

Upvotes: 3

Related Questions