0

I wanted to construct a manual legend, using ggplot in R.

Following this post: Construct a manual legend for a complicated plot, I constructed a manual legend for my plot.(reproducible example at bottom of post)

I'm not sure what I'm doing wrong, but the legends do not show. The most common answer out on the internet is appointing a color or fill inside your aesthetic, but I believe I did that (?). I'm working with two different dataframes, might that be the issue?

Any help is nice, here's the code (data below):

#plot effect of external ROI negative influence
cols <- c("Yes"="#4730ff","No"="#07BEB8")

EP_ROI <- ggplot() +
  geom_ribbon(data=external_ROI,aes(x=month,ymin=div - divsd, ymax=div + divsd,fill="No"),alpha=0.12,fill="#4730ff") +
  geom_line(data=external_ROI,aes(x=month,y=div,group=1,colour="Yes"),colour="#4730ff",size=1) +
  geom_vline(aes(xintercept=73),colour="#4730ff",linetype="dashed") +
  geom_vline(aes(xintercept=130),colour="#4730ff",linetype="dashed") +
  labs(y="return on investment (ROI)", x="time (months)") +
  geom_ribbon(data=noexternal_ROI,aes(x=month,ymin=div - divsd, ymax=div + divsd,fill="No"),alpha=0.12,fill="#07BEB8") +
  geom_line(data=noexternal_ROI,aes(x=month,y=div,group=1,colour="No"),colour="#07BEB8",size=1) +
  annotate(x=103, y=7.3,label=paste("external ROI\ninfluence period"), geom="text", color="#4730ff", size=3) +
  scale_colour_manual(name="External influence",values=cols) +
  scale_fill_manual(name="standard deviation",values=cols)

my data:

> dput(head(external_ROI))
structure(list(month = 0:5, n = c(0, 16.9, 16.9, 16.9, 16.9, 
16.9), ids = c(0, 16.9, 16.9, 16.9, 16.9, 16.9), ids_sd = c(0, 
7.83075094292788, 7.83075094292788, 7.83075094292788, 7.83075094292788, 
7.83075094292788), prods = c(0, 0, 0, 0, 0, 0), prods_sd = c(0, 
0, 0, 0, 0, 0), cons = c(0, 0, 0, 0, 0, 0), cons_sd = c(0, 0, 
0, 0, 0, 0), strat = c(0, 0, 0, 0, 0, 0), strat_sd = c(0, 0, 
0, 0, 0, 0), div = c(0, 0, 0, 0, 0, 0), divsd = c(0, 0, 0, 0, 
0, 0), REf = c(0, 0, 0, 0, 0, 0), part = c(NaN, 0, 0.341557936787342, 
0.343963785131726, 0.348913136282736, 0.354318810222323), shares = c(0, 
1.48042413246047, 1.48042413246047, 1.48042413246047, 1.48042413246047, 
1.48042413246047)), .Names = c("month", "n", "ids", "ids_sd", 
"prods", "prods_sd", "cons", "cons_sd", "strat", "strat_sd", 
"div", "divsd", "REf", "part", "shares"), row.names = c(NA, -6L
), class = c("tbl_df", "tbl", "data.frame"))

> dput(head(noexternal_ROI))
structure(list(month = 0:5, n = c(0, 16.9, 16.9, 16.9, 16.9, 
16.9), ids = c(0, 16.9, 16.9, 16.9, 16.9, 16.9), ids_sd = c(0, 
7.83075094292788, 7.83075094292788, 7.83075094292788, 7.83075094292788, 
7.83075094292788), prods = c(0, 0, 0, 0, 0, 0), prods_sd = c(0, 
0, 0, 0, 0, 0), cons = c(0, 0, 0, 0, 0, 0), cons_sd = c(0, 0, 
0, 0, 0, 0), strat = c(0, 0, 0, 0, 0, 0), strat_sd = c(0, 0, 
0, 0, 0, 0), div = c(0, 0, 0, 0, 0, 0), divsd = c(0, 0, 0, 0, 
0, 0), REf = c(0, 0, 0, 0, 0, 0), part = c(NaN, 0, 0.347981045925851, 
0.346991946002129, 0.349521295784053, 0.354625736233002), shares = c(0, 
1.47284681870507, 1.47284681870507, 1.47284681870507, 1.47284681870507, 
1.47284681870507)), .Names = c("month", "n", "ids", "ids_sd", 
"prods", "prods_sd", "cons", "cons_sd", "strat", "strat_sd", 
"div", "divsd", "REf", "part", "shares"), row.names = c(NA, -6L
), class = c("tbl_df", "tbl", "data.frame"))
maria118code
  • 153
  • 1
  • 14
  • 2
    You aren't using either `fill` or `colour` as an aesthetic, so they won't appear in a legend. Your `fill="No"` in the aesthetic is just setting it to a constant value. – Andrew Gustar Jun 07 '18 at 11:02
  • You correctly put `fill`/`color` mapped to a constant inside `aes()` but then you wrote over that choice by also putting `fill`/`color` as a constant outside `aes()` in, e.g., your `geom_ribbon()` layer. If you remove your use of `fill` and `color` outside `aes()` things should work better. – aosmith Jun 07 '18 at 18:47
  • There's definitely some ways to clean this up to get it working. However, the sample of data you provided is pretty small, and doesn't contain any values of `div` or `divsd` that aren't 0, so there isn't much to visualize as of right now. – camille Jun 08 '18 at 19:02

1 Answers1

2

As mentioned in the comments, the legend isn't appearing because you are also setting the color and fill outside of the aes call, which overwrites the color assignments you are wanting.

The easiest way would be to combine your data into one tidy dataframe which will then work much better with ggplot and make the code easier to read.

# create fake dataframes
external_ROI <- data.frame(month=1:168, div = c(rnorm(72, 80,5), rnorm(58, 100, 5), rnorm(38, 80, 5)), divsd = rnorm(168, 3, 1))
noexternal_ROI <- data.frame(month=1:168, div = rnorm(168, 80,5), divsd = rnorm(168, 4, 1))
# combine into one dataframe that is tidy
external_ROI$influence <- "No"
noexternal_ROI$influence <- "Yes"
combined.df <- rbind(external_ROI, noexternal_ROI)

#example
library(ggplot2)
#plot effect of external ROI negative influence
cols <- c("Yes"="#4730ff","No"="#07BEB8")

ggplot(data = combined.df) +
  geom_ribbon(aes(x = month, ymin = div - divsd, ymax = div + divsd, 
                                      fill = influence), alpha = 0.12) +
  geom_line(aes(x = month, y = div, colour = influence,), size = 1) +
  geom_vline(aes(xintercept = 73), colour = "#4730ff", linetype = "dashed") +
  geom_vline(aes(xintercept = 130), colour = "#4730ff", linetype = "dashed") +
  labs(y = "return on investment (ROI)", x = "time (months)") +
  annotate(x=103, y=7.3,label=paste("external ROI\ninfluence period"), geom="text", color="#4730ff", size=3) +
  scale_colour_manual(name= "External influence", values = cols) +
  scale_fill_manual(name= "standard deviation", values = cols)

If you don't want to create extra objects in your environment, you could also use a pipe to combine them and plot in one call. F

m.evans
  • 606
  • 3
  • 15