0
votes
#Plot the in sample forecasts against the actual values
#Build the confidence interval

Upper95 <- fcast1 + 1.96*sqrt(Var1)

Lower95 <- fcast1 - 1.96*sqrt(Var1)

Upper80 <- fcast1 + 1.28*sqrt(Var1)

Lower80 <- fcast1 - 1.28*sqrt(Var1)
#Create a data frame

dfb <- data.frame(TeslaWeeklyPrices$Date,fcast1,TeslaWeeklyPrices$TeslaPrices,Upper95,Lower95,Upper80,Lower80)
#Make the Plot

Plot1 <- ggplot(dfb, aes(x=TeslaWeeklyPrices.Date, y=TeslaWeeklyPrices.TeslaPrices))+ 
  geom_ribbon(data=dfb,aes(ymin=Upper95,ymax=Lower95),fill = "slategray2")+ 

  geom_ribbon(data=dfb,aes(ymin=Upper80,ymax=Lower80),fill = "bisque")+ 

  geom_line(data=dfb, aes(x=TeslaWeeklyPrices.Date, y=fcast1),size=1, color="red1")+

  geom_point(shape = 19,  fill = "white", colour = "blue" ,size = 1)+ 

  theme_light(base_size = 11) +

  ylab("Tesla Stock price ($)") + xlab("Date (weeks)")

Plot1  

That is my code for my graph.

enter image description here

That is how it looks. I want to add legends in my graph without having to tidy my data. Because then I can not format my graph as I want.

After the useful comment I got.

Upper95 <- fcast1 + 1.96*sqrt(Var1)

Lower95 <- fcast1 - 1.96*sqrt(Var1)

Upper80 <- fcast1 + 1.28*sqrt(Var1)

Lower80 <- fcast1 - 1.28*sqrt(Var1)

dfb <- data.frame(TeslaWeeklyPrices$Date,fcast1,TeslaWeeklyPrices$TeslaPrices,Upper95,Lower95,Upper80,Lower80)

Plot1 <- ggplot(dfb, aes(x=TeslaWeeklyPrices.Date, y=TeslaWeeklyPrices.TeslaPrices))+

geom_ribbon(aes(ymin=Upper95, ymax=Lower95, fill='95% prediction level')) +

geom_ribbon(aes(ymin=Upper80, ymax=Lower80, fill='80% prediction level')) +

geom_line(data=dfb, aes(x=TeslaWeeklyPrices.Date, y=fcast1, color="Predicted Values"),size=1)+

geom_point(shape = 19, aes(color = "Observed Values"), fill = "white", size = 1 ,)+

scale_fill_manual(values=c('95% prediction level'='slategray2', '80% prediction level'="bisque"), breaks=c('95% prediction level', '80% prediction level')) +

scale_color_manual(values=c("Predicted Values"="red","Observed Values"= "blue"), breaks=c('Predicted Values', 'Observed Values'))+ guides(color=guide_legend(title=NULL),fill=guide_legend(title=NULL) ) +

theme(legend.margin = margin(b=0, t=-1000))+

theme_light(base_size = 12)

Plot1

That is my new code. enter image description here

So how can my blue points look as points in the Legend and not as a line. And how can i det the margin to 0 between my 2 legends?

enter image description here

Can I format the background color of this so it looks like an independent part and not as part of the graph?

enter image description here

That is an example I saw in one paper.

1

1 Answers

0
votes

First of all, I do have a bit of an issue with the comment:

I want to add legends in my graph without having to tidy my data. Because then I can not format my graph as I want.

Tidying your data is often the best solution to do just that (format the graph as you want), but I kind of agree it might be more straightforward in this case to just "brute force" the legend into place. I'll show you how.

Since I don't have your data, I made up my own to mirror that you shared:

set.seed(1234)

time <- 1:50
Var1 <- unlist(lapply(time, function(x) rnorm(1, 1, 0.01)))
fcast1 <- unlist(lapply(time, function(x) { x * rnorm(1, 0.1, 0.01)}))
Upper95 <- fcast1 + 1.96*sqrt(Var1)
Lower95 <- fcast1 - 1.96*sqrt(Var1)
Upper80 <- fcast1 + 1.28*sqrt(Var1)
Lower80 <- fcast1 - 1.28*sqrt(Var1)

dfb <- data.frame(time, fcast1, Upper95, Lower95, Upper80, Lower80)

And the plot:

ggplot(dfb, aes(time, fcast1)) +
  geom_ribbon(aes(ymin=Upper95, ymax=Lower95), fill='slategray2') +
  geom_ribbon(aes(ymin=Upper80, ymax=Lower80), fill='bisque') +
  geom_line(size=1, color='red1') +
  theme_light()

enter image description here

To create the legend without having Tidy data, you need to make the legend piece by piece, but still use ggplot to do so. Legends are created for aesthetics that are not part of the coordinate system in ggplot2 that are inside of aes(). Therefore, to make the legend appear, you only need to put the aesthetic modifiers fill and color inside the aes() part of each geom_*() function.

It's not quite that simple though, but once you understand how it works it becomes more clear. The value you assign to fill= or color= inside aes() will be used for the label in the legend, and not the color. You will have to specify color with a scale_*() function.

ggplot(dfb, aes(time, fcast1)) +
  geom_ribbon(aes(ymin=Upper95, ymax=Lower95, fill='Upper')) +
  geom_ribbon(aes(ymin=Upper80, ymax=Lower80, fill='Lower')) +
  geom_line(size=1, aes(color="Forecast")) +
  scale_fill_manual(values=c('Upper'='slategray2', 'Lower'='bisque'), breaks=c('Upper', 'Lower')) +
  scale_color_manual(values='red1') +
  theme_light()

enter image description here

That looks more like it, but it's not perfect. Perhaps you would want the line and fill boxes in the legend to become "one" legend box instead? If that's the case, you can't really do that (because they span two different aesthetic modifiers, fill and color); however, we can make the same effect if we do a few things:

  1. Remove the title for the color legend
  2. Change the title for the fill legend
  3. Use the theme elements and margins to move the legends closer together to look as one

Here you can see how you might do that:

p + # this is the code from above
  guides(
    color=guide_legend(title=NULL),
    fill=guide_legend(title='Legend')
  ) +
  theme(legend.margin = margin(b=0, t=-13))

enter image description here

EDIT:

OP asked if the points could appear on the chart as well. They certainly can, and you have to use a similar method to do that. You can just add color= into aes() for geom_point() like before:

ggplot(dfb, aes(time, fcast1)) +
  geom_ribbon(aes(ymin=Upper95, ymax=Lower95, fill='Upper')) +
  geom_ribbon(aes(ymin=Upper80, ymax=Lower80, fill='Lower')) +
  geom_line(size=1, aes(color="Forecast")) +
  geom_point(size=1, aes(color='Actual Values'), shape=19) +
  scale_fill_manual(values=c('Upper'='slategray2', 'Lower'='bisque'), breaks=c('Upper', 'Lower')) +
  scale_color_manual(values=c('Forecast'='red1', 'Actual Values'='blue')) +
  theme_light() +
  guides(
    color=guide_legend(title=NULL),
    fill=guide_legend(title='Legend')
  ) +
  theme(legend.margin = margin(b=0, t=-13))

enter image description here

One small problem there... you'll notice the icon (called "glyph") next to "Actual Values" and "Forecast" is a line + a point. I think you'd prefer to have a point be the glyph for the point and a line be the glyph for the line. We can't do that in the same legend (they are both part of the color legend)... so we can fix that by separating "Actual Values" into another legend. In this case, we'll just use the shape aesthetic modifier and have a third legend that also has no title.

ggplot(dfb, aes(time, fcast1)) +
  geom_ribbon(aes(ymin=Upper95, ymax=Lower95, fill='Upper')) +
  geom_ribbon(aes(ymin=Upper80, ymax=Lower80, fill='Lower')) +
  geom_line(size=1, aes(color="Forecast")) +
  geom_point(size=1, aes(shape='Actual Values'), color='blue') +
  scale_fill_manual(values=c('Upper'='slategray2', 'Lower'='bisque'), breaks=c('Upper', 'Lower')) +
  scale_color_manual(values=c('Forecast'='red1')) +
  scale_shape_manual(values=19) +
  theme_light() +
  guides(
    color=guide_legend(title=NULL),
    shape=guide_legend(title=NULL),
    fill=guide_legend(title='Legend')
  ) +
  theme(legend.margin = margin(b=0, t=-13))

enter image description here

Now you have all the information needed to become a ggplot master :).