0
votes

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"))
1
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
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
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

1 Answers

2
votes

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