adding custom ggplot legend to dashed lines and confidence bands - r

I'm having trouble setting a custom legend for confidence bands and dashed lines. This is my graph so far.
di<-matrix(ncol = 3,nrow = 5) %>% as.data.frame()
colnames(di)<-c('group','estimate','SE')
di<-di %>% mutate(group=1:5,
estimate=c(0.5,9.6,13,15,23.1),
SE=14)
ggplot(di, aes(x=group, y=estimate)) +
geom_point() +
geom_errorbar(width=.5, aes(ymin=estimate-(1.647*SE), ymax=estimate+(1.647*SE)), colour="black") +
xlab('Group') +
ylab('Treatment Effect') +
labs(title="GATE with confidence bands",
subtitle="Point estimates and confidence bands are derived using median of all splits") +
geom_hline(yintercept=c(7.83,22.55),
linetype="longdash",
col='darkred') +
geom_hline(yintercept=15.19,
linetype="longdash",
col='blue')
It looks like this:
However what I want it to look like is something like this, with the exact same legend:
Any advice on this?

This could be achieved like so:
As a general rule: If you want to have a legend you have to map something on aesthetics, e.g. move color=... into aes() for all four geoms
The desired color values can then be set via scale_color_manual
For the geom_hline we also have to pass yintercept as an aes() too. To this end these get something helper data frames with the desired values.
To fix the lines and shapes in the legend I make use of guide_legend's overide.aes to remove the undesired points in the legend as well as removing the line for the point. Additionally I set the number of rows for the legend to 2.
The labels and the order of the layers can be set via the labels and the breaks argument of scale_color_manual
Move the legend in the topleft and get rid of the background fill for the legend and the keys via theme options.
library(ggplot2)
di <- data.frame(
group = 1:5,
estimate = c(0.5, 9.6, 13, 15, 23.1),
SE = 14
)
labels <- c(point = "Point", error = "Error", blue = "Blue", darkred = "Red")
breaks <- c("blue", "darkred", "point", "error")
ggplot(di, aes(x = group, y = estimate)) +
geom_point(aes(color = "point"), size = 3) +
geom_errorbar(width = .5, aes(
ymin = estimate - (1.647 * SE),
ymax = estimate + (1.647 * SE),
color = "error"
)) +
scale_color_manual(values = c(
point = "black",
error = "black",
blue = "blue",
darkred = "darkred"
), labels = labels, breaks = breaks) +
labs(
title = "GATE with confidence bands",
subtitle = "Point estimates and confidence bands are derived using median of all splits",
x = "Group",
y = "Treatment Effect",
color = NULL, linetype = NULL, shape = NULL
) +
geom_hline(
data = data.frame(yintercept = c(7.83, 22.55)),
aes(yintercept = yintercept, color = "darkred"), linetype = "longdash"
) +
geom_hline(
data = data.frame(yintercept = 15.19),
aes(yintercept = yintercept, color = "blue"), linetype = "longdash"
) +
guides(color = guide_legend(override.aes = list(
shape = c(NA, NA, 16, NA),
linetype = c("longdash", "longdash", "blank", "solid")
), nrow = 2, byrow = TRUE)) +
theme(legend.position = c(0, 1),
legend.justification = c(0, 1),
legend.background = element_rect(fill = NA),
legend.key = element_rect(fill = NA))

Related

Adjust ggplot legend

I am trying to make the following changes to the ggplot below (partly illustrated in the picture provided):
change shading legend to show economic cycle (shaded is a recession, no shade is an expansion)
add additional legend to show economic variables (green is 'CLI' and red is 'Inflation Expectations")
The code so far looks like this:
A <- ggplot(Alldata, aes(Date)) +
geom_tile(aes(alpha = Recession, y = 1),
fill = "grey", height = Inf) +
scale_alpha_continuous(range = c(0, 1), breaks = c(0, 1))+
geom_line(aes(y = stdINFEX), col = 'blue', size = .8)+
ylab('')+
theme( axis.text.y=element_blank(), #remove y axis labels
axis.ticks.y=element_blank() #remove y axis ticks
)
A
B <- A + geom_line(aes(y = CLI), col = 'green', size = .8)
B
Maybe this is what you are looking for:
You could set the labels for legend entries via the labels argument of the scale, e.g. using a named vector you could assign a label Expansion to the value "0"
To get a legend for your lines you have to map on aesthetics, i.e. move color=... inside of aes(). Note that using color names inside aes() is meaningless. Therefore I would suggest to use meaningful labels. You could then set your desired colors via scale_color_manual.
Finally, to set the labels for your legends you could make use of labs()
As you provided no example data (see how to make a minimal reproducible example) I make use of the ggplot2::economics dataset as example data:
library(ggplot2)
set.seed(123)
economics$Recession <- 0
economics$Recession[sample(1:nrow(economics), 100)] <- 1
ggplot(economics, aes(date)) +
geom_tile(aes(alpha = Recession, y = 1),
fill = "grey", height = Inf
) +
scale_alpha_continuous(range = c(0, 1),
breaks = c(0, 1),
labels = c("0" = "Expansion", "1" = "Recession")) +
geom_line(aes(y = psavert, color = "psavert"), size = .8) +
geom_line(aes(y = uempmed, color = "uempmed"), size = .8) +
scale_color_manual(values = c(psavert = "blue", uempmed = "green")) +
labs(y = NULL, alpha = "Economic Cycle", color = "Economic Variable") +
theme(
axis.text.y = element_blank(),
axis.ticks.y = element_blank()
)

Combine legend for fill and colour ggplot to give only single legend

I am plotting a smooth to my data using geom_smooth and using geom_ribbon to plot shaded confidence intervals for this smooth. No matter what I try I cannot get a single legend that represents both the smooth and the ribbon correctly, i.e I am wanting a single legend that has the correct colours and labels for both the smooth and the ribbon. I have tried using + guides(fill = FALSE), guides(colour = FALSE), I also read that giving both colour and fill the same label inside labs() should produce a single unified legend.
Any help would be much appreciated.
Note that I have also tried to reset the legend labels and colours using scale_colour_manual()
The below code produces the below figure. Note that there are two curves here that are essentially overlapping. The relabelling and setting couours has worked for the geom_smooth legend but not the geom_ribbon legend and I still have two legends showing which is not what I want.
ggplot(pred.dat, aes(x = age.x, y = fit, colour = tagged)) +
geom_smooth(size = 1.2) +
geom_ribbon(aes(ymin = lci, ymax = uci, fill = tagged), alpha = 0.2, colour = NA) +
theme_classic() +
labs(x = "Age (days since hatch)", y = "Body mass (g)", colour = "", fill = "") +
scale_colour_manual(labels = c("Untagged", "Tagged"), values = c("#3399FF", "#FF0033")) +
theme(axis.title.x = element_text(face = "bold", size = 14),
axis.title.y = element_text(face = "bold", size = 14),
axis.text.x = element_text(size = 12),
axis.text.y = element_text(size = 12),
legend.text = element_text(size = 12))
The problem is that you provide new labels for the color-aesthetic but not for the fill-aesthetic. Consequently ggplot shows two legends because the labels are different.
You can either also provide the same labels for the fill-aesthetic (code option #1 below) or you can set the labels for the levels of your grouping variable ("tagged") before calling ggplot (code option #2).
library(ggplot2)
#make some data
x = seq(0,2*pi, by = 0.01)
pred.dat <- data.frame(x = c(x,x),
y = c(sin(x), cos(x)) + rnorm(length(x) * 2, 0, 1),
tag = rep(0:1, each = length(x)))
pred.dat$lci <- c(sin(x), cos(x)) - 0.4
pred.dat$uci <- c(sin(x), cos(x)) + 0.4
#option 1: set labels within ggplot call
pred.dat$tagged <- as.factor(pred.dat$tag)
ggplot(pred.dat, aes(x = x, y = y, color = tagged, fill = tagged)) +
geom_smooth(size = 1.2) +
geom_ribbon(aes(ymin = lci, ymax = uci), alpha = 0.2, color = NA) +
scale_color_manual(labels = c("untagged", "tagged"), values = c("#F8766D", "#00BFC4")) +
scale_fill_manual(labels = c("untagged", "tagged"), values = c("#F8766D", "#00BFC4")) +
theme_classic() + theme(legend.title = element_blank())
#option 2: set labels before ggplot call
pred.dat$tagged <- factor(pred.dat$tag, levels = 0:1, labels = c("untagged", "tagged"))
ggplot(pred.dat, aes(x = x, y = y, color = tagged, fill = tagged)) +
geom_smooth(size = 1.2) +
geom_ribbon(aes(ymin = lci, ymax = uci), alpha = 0.2, color = NA) +
theme_classic() + theme(legend.title = element_blank())

Is there a way to make ggplot2 legend show all unique combinations of aesthetics?

I have created a plot which shows two factors, each with two levels. I have shown these using colour and alpha aesthetics. My legend only shows these aesthetics separately. Is there a way to show all unique combinations of the aesthetics with alpha and colour combined? Thank you for your help!
Picture of plot compared with desired plot
Here is the relevant code (with some irrelevant parts removed):
ggplot(data, aes(x = Session, y = group_mean, group = FactorA:FactorB))+
geom_line(aes(colour = FactorA, alpha = FactorB, group = FactorA:FactorB), linetype = "solid", size = 0.7)+
geom_point(aes(y=group_mean, colour = FactorA, alpha = FactorB, group = FactorA:FactorB), shape = 18, size = 4, position=position_dodge(0.5))+
scale_fill_brewer(palette = "Set1", name = "FactorA")+
scale_colour_brewer(palette = "Set1")+
scale_alpha_manual(values = c(0.4, 0.8)) +
guides(colour = guide_legend(order = 1),
fill = guide_legend(order = 1),
alpha = guide_legend(order = 2))

R ggplot2::geom_vline legend not displaying line type correctly

I'm trying this simple task in which I wish to add two vertical lines to a ggplot object, with different colours and different line types, and colours/lines correctly specified in a legend. I've been looking at this post in which two geom_vlines are plotted. If you change one of their line types e.g. to solid, the legend wrongly displays the line types. It turns all lines to solids.
library(ggplot2)
library(ggthemes)
ggplot(aes(x = Sepal.Length), data = iris) +
geom_histogram(color = 'black', fill = NA) +
geom_vline(aes(xintercept = median(iris$Sepal.Length),
color = "median"),
linetype = "solid", size = 1) +
geom_vline(aes(xintercept = mean(iris$Sepal.Length),
color = "mean"),
linetype = "dashed", size = 1) +
scale_color_manual(
name = "statistics",
values = c(median = "blue", mean = "red"))
I also tried simply the following without any added data:
library(ggplot2)
library(ggthemes)
ggplot() + theme_bw() +
geom_vline(aes(xintercept = c(0, 0.2),
color = c("Zero", "Pooled")),
size = 1, linetype = c("solid", "dotdash")) +
scale_color_manual(
name = "statistics",
values = c(Zero = "black", Pooled = "blue"))
in which the linetypes were wrongly displayed on the legend.
Can anyone pinpoint me to what's going on and how I can get the line types to display correctly?
You can put linetype in the aes call, the same way you did for colour:
ggplot(aes(x = Sepal.Length), data = iris) +
geom_histogram(color = 'black', fill = NA) +
geom_vline(aes(xintercept = median(iris$Sepal.Length),
color = "median", linetype = 'median'),
size = 1) +
geom_vline(aes(xintercept = mean(iris$Sepal.Length),
color = "mean", linetype = "mean"),
size = 1) +
scale_color_manual(
name = "statistics",
values = c(median = "blue", mean = "red")) +
scale_linetype_manual(
name = "statistics",
values = c(median = "solid", mean = "dashed"))
Using named vectors when you're specifying which value matches up to which linetype also helps - I think the reason your second example fails is that in the legend, ggplot assigns the linetypes to the levels in alphabetical order.
Output:

Create legend with manual shapes and colours

I use bars and line to create my plot. The demo code is:
timestamp <- seq(as.Date('2010-01-01'),as.Date('2011-12-01'),by="1 mon")
data1 <- rnorm(length(timestamp), 3000, 30)
data2 <- rnorm(length(timestamp), 30, 3)
df <- data.frame(timestamp, data1, data2)
p <- ggplot()
p <- p + geom_histogram(data=df,aes(timestamp,data1),colour="black",stat="Identity",bindwidth=10)
p <- p + geom_line(data=df,aes(timestamp,y=data2*150),colour="red")
p <- p + scale_y_continuous(sec.axis = sec_axis(~./150, name = "data2"))
p <- p + scale_colour_manual(name="Parameter", labels=c("data1", "data2"), values = c('black', 'red'))
p <- p+ scale_shape_manual(name="Parameter", labels=c("data1", "data2"), values = c(15,95))
p
This results in a plot like this:
This figure does not have a legend. I followed this answer to create a customized legend but it is not working in my case. I want a square and line shape in my legend corresponding to bars and line. How can we get it?
I want legend as shown in below image:
For the type of data you want to display, geom_bar is a better fit then geom_histogram. When you to manipulate the appaerance of the legend(s), you need to place the colour = ... parts inside the aes. To get the desired result it probably best to use different types of legend for the line and the bars. In that way you are better able to change the appearance of the legends with guide_legend and override.aes.
A proposal for your problem:
ggplot(data = df) +
geom_bar(aes(x = timestamp, y = data1, colour = "black"),
stat = "Identity", fill = NA) +
geom_line(aes(x = timestamp, y = data2*150, linetype = "red"), colour = "red", size = 1) +
scale_y_continuous(sec.axis = sec_axis(~./150, name = "data2")) +
scale_linetype_manual(labels = "data2", values = "solid") +
scale_colour_manual(name = "Parameter\n", labels = "data1", values = "black") +
guides(colour = guide_legend(override.aes = list(colour = "black", size = 1),
order = 1),
linetype = guide_legend(title = NULL,
override.aes = list(linetype = "solid",
colour = "red",
size = 1),
order = 2)) +
theme_minimal() +
theme(legend.key = element_rect(fill = "white", colour = NA),
legend.spacing = unit(0, "lines"))
which gives:

Resources