1

I would like to add a legend to this but am struggling to find out how. Can someone please help?

  df1 <- data.frame(Rate=rnorm(10, 500, 100), Damage=rnorm(10, 50, 15))
  x1 <- data.frame(R=rnorm(20, 550, 50), V=rnorm(20, 35, 10))

  ggplot(df1,aes(x=Rate,y=Damage)) +
  geom_smooth(method="auto",se=FALSE) +
  geom_smooth(data=x1, mapping=aes(x=R, y=V), 
  method="auto",col="firebrick",se=FALSE) +
  coord_cartesian(xlim=c(0,1000), ylim=c(0, 100)) +
  ggtitle("", subtitle="PPS post-emergence") +
  theme_bw() +
  scale_y_continuous(breaks=seq(0, 100, 20),) +
  xlab("Rate (mg/Ha)") +
  ylab("")
pogibas
  • 27,303
  • 19
  • 84
  • 117
  • Linked question is very similar to yours. Add `aes` for each `geom_smooth` with `color = ...` and specify wanted color with `scale_color_manual` (in case you needed legend for color). – pogibas Dec 12 '18 at 16:49
  • Why not rbind then plot? – zx8754 Dec 12 '18 at 17:01

2 Answers2

2

The easiest way to do what you want is to merge your data. But you can also do a manual color mapping. I'll show you both below.

Without merging your data

You want to create a manual color scale. The trick is to pass the color in aes then add a scale_color_manual to map names to colors.

ggplot(df1,aes(x=Rate,y=Damage)) +
  geom_smooth(aes(col = "val1"), method="auto",se=FALSE) +
  geom_smooth(data=x1, mapping=aes(x=R, y=V, col="val2"), 
              method="auto",se=FALSE) +
  coord_cartesian(xlim=c(0,1000), ylim=c(0, 100)) +
  ggtitle("", subtitle="PPS post-emergence") +
  theme_bw() +
  scale_y_continuous(breaks=seq(0, 100, 20),) +
  xlab("Rate (mg/Ha)") +
  ylab("") +
  scale_color_manual("My legend", values=c("val1" = "firebrick", 
                                           "val2" = "steelblue"))

Plot with legend

Less lines by using labs

By the way, there is a simpler way to set the title (or subtitle) and axis labels with labs. You don't have to pass a title so you gain some vertical space and passing NULL (instead of "") as the y label actually removes it which gains some horizontal space.

Below, the picture is the same size but the graph occupies a larger part of it.

ggplot(df1,aes(x=Rate,y=Damage)) +
  geom_smooth(aes(col = "val1"), method="auto",se=FALSE) +
  geom_smooth(data=x1, mapping=aes(x=R, y=V, col="val2"), 
              method="auto",se=FALSE) +
  coord_cartesian(xlim=c(0,1000), ylim=c(0, 100)) +
  theme_bw() +
  scale_y_continuous(breaks=seq(0, 100, 20),) +
  labs(subtitle="PPS post-emergence", 
       x = "Rate (mg/Ha)",
       y = NULL) +
  scale_color_manual("My legend", values=c("val1" = "firebrick", 
                                           "val2" = "steelblue"))

Plot using labs instead of ggtitle

Merging your data

The best way of doing it would actually be to merge your data while keeping track of the source, then use source as the color. Much cleaner but not always possible.

df <- bind_rows(
  mutate(df1, source="df1"),
  x1 %>% rename(Rate = R, Damage = V) %>%
    mutate(source="x1")
)

ggplot(df, aes(x=Rate, y=Damage, col=source)) +
  geom_smooth(method="auto", se=FALSE) +
  coord_cartesian(xlim=c(0,1000), ylim=c(0, 100)) +
  theme_bw() +
  scale_y_continuous(breaks=seq(0, 100, 20),) +
  labs(subtitle="PPS post-emergence", 
       x = "Rate (mg/Ha)",
       y = NULL)

enter image description here

asachet
  • 6,620
  • 2
  • 30
  • 74
0

We could row bind then plot:

library(ggplot2)
library(dplyr)

set.seed(1)
df1 <- data.frame(Rate=rnorm(10, 500, 100), Damage=rnorm(10, 50, 15))
x1 <- data.frame(R=rnorm(20, 550, 50), V=rnorm(20, 35, 10))

plotDat <- rbind(df1 %>% transmute(x = Rate, y = Damage, grp = "df1"),
                 x1 %>% transmute(x = R, y = V, grp = "x1"))

ggplot(plotDat, aes(x, y, col = grp)) +
  geom_smooth(se = FALSE)

enter image description here

zx8754
  • 52,746
  • 12
  • 114
  • 209