Reputation: 678
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
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)
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)
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
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)
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)
Upvotes: 5
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)
Upvotes: 3