Trying to add legend using geom_abline - r

I have a data frame, saved as df, with two columns of points that I would like to plot. In addition, I would like to plot two lines on the plot and would like to have a legend for these lines. Here is my code:
ggplot(df, aes(x = x, y = y)) +
geom_point(color = "black", shape = 16, alpha = 1) +
scale_x_continuous(name = "x", limits = c(-5, 5)) +
scale_y_continuous(name = "y", limits = c(-5, 5)) +
geom_abline(intercept = 0, slope = 4/3, linetype = "dashed",
color = "gray40", size = 1, aes(colour = "XNULL")) +
geom_abline(intercept = 0, slope = 0, linetype = "dotted",
color = "gray40", size = 1, aes(colour = "YNULL")) +
scale_color_manual(name = "", values = c("XNULL" = "red", "YNULL" = "blue")) +
theme(panel.background = element_rect(fill = "white"),
panel.border = element_rect(colour = "black", fill = NA, size = 1),
legend.position = "bottom")
However, when I run this, no legend comes up (I would like to have the legend on the bottom). Any suggestions as to what I am doing wrong? I am new at using ggplot2, and none of the solutions I looked up on other forums helped.

You can try creating another data.frame to contain information about your ablines:
df = data.frame(x=runif(10),y=runif(10))
df2 = data.frame(intercept=0,slope=c(4/3,0),type=c("XNULL","YNULL"))
Then we can call geom_abline specifying the aes so that we can use
ggplot(df, aes(x = x, y = y)) +
geom_point(color = "black", shape = 16, alpha = 1) +
scale_x_continuous(name = "x", limits = c(-5, 5)) +
scale_y_continuous(name = "y", limits = c(-5, 5)) +
geom_abline(data=df2,aes(intercept=intercept,slope=slope,
linetype=type,col=type),size = 1) +
scale_color_manual(name = "", values = c("XNULL" = "red", "YNULL" = "blue")) +
scale_linetype_manual(name = "", values = c("XNULL" = "dashed", "YNULL" = "dotted")) +
theme(panel.background = element_rect(fill = "white"),
panel.border = element_rect(colour = "black", fill = NA, size = 1),
legend.position = "bottom")

From the documentation:
These geoms act slightly differently from other geoms. You can supply
the parameters in two ways: either as arguments to the layer function,
or via aesthetics. If you use arguments, e.g. geom_abline(intercept =
0, slope = 1), then behind the scenes the geom makes a new data frame
containing just the data you've supplied.
Apparently, you have to specify intercept and slope in aes, so that it works.
library(ggplot2)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point() +
coord_cartesian(xlim = c(0,10), ylim = c(0,10)) +
geom_abline(aes(intercept = 0, slope = 0, color = "X"), linetype = "dotted") +
geom_abline(aes(intercept = 0, slope = 4/3, color = "Y"),linetype = "dashed") +
scale_color_manual(values = c(X = 'grey', Y = 'black'))
Created on 2020-02-12 by the reprex package (v0.3.0)

Related

ggplot2 plot points when y value in NA

I have a dataframe where the x value (discrete) is present and want to include on the x-axis in the plot; however, its y value is NA
I still want to show the x value even though y is NA. Is there a way to do this in ggplot2?
Currently, it simply skips the first two rows that has the NA value.
ggplot(tChartDF()[['df']], aes(
x = factor(tChartDF()[['df']][['Rare event date']], levels = unique(tChartDF()[['df']][['Rare event date']])),
y = unlist(tChartDF()[['df']][['days_between']]),
)) +
geom_hline(yintercept = unlist(tChartDF()[['timeScaleCL']]), color = input$tChartCLColour, lwd = input$tChartCLWidth) +
geom_hline(yintercept = unlist(tChartDF()[['timeScaleUL']]), linetype = 'dashed', lwd = 1, color = 'red') +
geom_hline(yintercept = unlist(tChartDF()[['timeScaleLL']]), linetype = 'dashed', lwd = 1, color = 'red') +
scale_x_discrete(expand = c(0,0)) +
theme_classic() +
geom_line(aes(group = 1), lwd = input$tChartLineWidth, color= input$tChartLineColour) +
geom_point(size = input$tChartMarkerSize, color = input$tChartMarkerColour) +
labs(title = input$tChartPlotTitle, x = input$tChartPlotXLabel, y = input$tChartPlotYLabel) +
theme(
plot.title = element_text(size = 24, face = 'bold', family = 'Arial', hjust = 0.5),
plot.margin = margin(0, 1, 0, 0, "cm"),
axis.title = element_text(size = 20, face = 'bold', family = 'Arial'),
axis.text = element_text(size = 16, face = 'bold', family = 'Arial'),
axis.text.x = element_text(angle = as.numeric(input$tChartXOrientation), vjust = 0.5),
axis.ticks.length = unit(.25, 'cm'),
) +
coord_cartesian(clip = 'off')
As seen, it only starts plotting at date: 2022/12/15 (ignoring the previous values in the table) columns y and mr have the NA values.
For the plot, I only care about the first two columns (Rare events and days_between). I tried selecting only those two columns and plotting but it still ignores the first two rows.
Desired result:
If we start with something like
mt <- mtcars
mt$mpg[c(3,6,9)] <- NA
and plot the line as in
ggplot(mt, aes(disp, mpg)) +
geom_line()
we don't see the missing points (not a surprise). We can add them this way:
transform(mt, mpg2 = ifelse(is.na(mpg), max(mpg, na.rm = TRUE) + 1, mpg)) |>
ggplot(aes(disp, mpg)) +
geom_line() +
geom_point(aes(y = mpg2), data = ~ subset(., is.na(mpg)), shape = 1)
This can easily be adapted to be at the bottom, using different shapes/colors, perhaps even on an explicitly-gray background (top/bottom ribbon).

Why does the ggplot legend show both line colour and linetype?

I want the legend to show a blue solid line for "Panel regression", and a grey dashed line for "y = x". Why does it show the diagonal dashed lines in the legend?
ggplot(df_REM24, aes(x=lngini_eurostat, y=fit_augment)) +
geom_point(size=1.5, shape=16, alpha=1) +
geom_smooth(method="lm", formula = y ~ x, aes(colour="blue")) +
geom_abline(linetype = 2, aes(slope = 1, intercept = 0, colour="red")) +
labs(x="Observed ln(Gini)", y="Predicted ln(Gini)") +
theme_few() +
scale_colour_manual(name='Legend',
labels = c("Panel regression", "y = x"),
values = c("#0072c3", "#737373")) +
theme(legend.position = c(.15, .9),
legend.key = element_rect(fill = "white", colour = "black", size=0.3),
legend.title = element_text(face = "bold"))
Also, I set the legend.key fill to white but it remains in grey.
First you should set show.legend = FALSE in your geom_abline. After that you can use this code to set white background in your boxes in the legend: guides(color = guide_legend(override.aes = list(fill = NA)), linetype = guide_legend(override.aes = list(fill = NA))) . You can use the following code (ps I created random data):
library(tidyverse)
library(ggthemes)
ggplot(df_REM24, aes(x=lngini_eurostat, y=fit_augment)) +
geom_point(size=1.5, shape=16, alpha=1) +
geom_smooth(method="lm", formula = y ~ x, aes(colour="blue")) +
geom_abline(linetype = 2, aes(slope = 1, intercept = 0, colour="red"), show.legend = FALSE) +
labs(x="Observed ln(Gini)", y="Predicted ln(Gini)") +
theme_few() +
scale_colour_manual(name='Legend',
labels = c("Panel regression", "y = x"),
values = c("#0072c3", "#737373")) +
theme(legend.position = c(.15, .9),
legend.key = element_rect(fill = "white", colour = "black", size=0.3),
legend.title = element_text(face = "bold")) +
guides(color = guide_legend(override.aes = list(fill = NA)), linetype = guide_legend(override.aes = list(fill = NA)))
Output:
Data
df_REM24 <- data.frame(lngini_eurostat = sort(runif(10, 3, 4)),
fit_augment = sort(runif(10, 3, 4)))
Should work with the missing bracket and without the aes in geom_smooth per this reproducible example with made-up data:
library(tidyverse)
tibble(x = rep(seq(2, 16, 1), 2),
y = abs(rnorm(30, 10, 10)),
colour = rep(c("fore", "hind"), 15)
) |>
ggplot(aes(x, y, colour = colour)) +
geom_point() +
geom_smooth(colour = "blue") +
theme(legend.key = element_rect(fill = "white"))
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
Created on 2022-05-04 by the reprex package (v2.0.1)

how to use facet_wrap to ggplot multiple location point in R?

I am trying to plot multiple location data using facet_wrap functionality of ggplot. I am having trouble in creating the legends (95% confidence interval is completely missed). Below is my code and I would appreciate any suggestion.
library(ggplot2)
library(lubridate)
set.seed(123)
DF1 <- data.frame(Date = seq(as.Date("2001-01-01"), to = as.Date("2005-12-31"), by = "1 month"),
Ob = runif(60,1,5), L95 =runif(60, 0,4), U95 = runif(60,2,7), Sim = runif(60,1,5),
Loc = rep("Upstream", 60))
DF2 <- data.frame(Date = seq(as.Date("2001-01-01"), to = as.Date("2005-12-31"), by = "1 month"),
Ob = runif(60,1,5), L95 =runif(60, 0,4), U95 = runif(60,2,7), Sim = runif(60,1,5),
Loc = rep("Downstream", 60))
DF <- dplyr::bind_rows(DF1,DF2)
DF$Loc <- factor(DF$Loc, levels = c("Upstream","Downstream"))
ggplot(DF, aes(x = Date))+
geom_ribbon(aes(ymin = L95, ymax = U95), fill = "grey30", alpha = 0.4)+
geom_line(aes(y = Ob, color = "blue"), size = 1 )+
geom_line(aes(y = Sim, color = "black"), size = 1, linetype = "dashed")+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
facet_wrap(~ Loc, ncol = 1, scales = "free_y")+
theme_bw()+
scale_color_identity(guide = "legend", breaks = c("grey30", "blue", "black"),
labels = c("95% confidence bound", "Observation","Simulation"))
Your fill is outside the aes function, so it cannot appear in the legend.
ggplot(DF, aes(x = Date))+
geom_ribbon(aes(ymin = L95, ymax = U95, color = "grey30"), fill = "grey30", alpha = 0.4)+
geom_line(aes(y = Ob, color = "blue"), size = 1 )+
geom_line(aes(y = Sim, color = "black"), size = 1, linetype = "dashed")+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
facet_wrap(~ Loc, ncol = 1, scales = "free_y")+
theme_bw()+
scale_color_identity(guide = "legend", breaks = c("grey30", "blue", "black"),
labels = c("95% confidence bound", "Observation","Simulation"))
ggplot(DF, aes(x = Date))+
geom_ribbon(aes(ymin = L95, ymax = U95, fill = "grey30"), alpha = 0.4)+
geom_line(aes(y = Ob, color = "blue"), size = 1 )+
geom_line(aes(y = Sim, color = "black"), size = 1, linetype = "dashed")+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
facet_wrap(~ Loc, ncol = 1, scales = "free_y")+
theme_bw()+
scale_color_identity(guide = "legend", breaks = c( "blue", "black"),
labels = c( "Observation","Simulation"),
name = 'Legend')+
scale_fill_identity(guide = "legend", labels = c("95% confidence bound"),
name=NULL)+
theme(legend.spacing.y = unit(-0.2, "cm"))+
theme(legend.title = element_text(margin=margin(b = 0.4, unit='cm')))
Here is how I would do this.
First, you are using fill for the ribbon, not color. Second, you need to actually map fill in aes, not just set it outside the aes. Then I would give the names you'd like in the aes calls, and use scale_*_manual to set the values you'd like:
ggplot(DF, aes(x = Date))+
geom_ribbon(aes(ymin = L95, ymax = U95, fill = "95% confidence bound"), alpha = 0.4)+
geom_line(aes(y = Ob, color = "Observation"), size = 1 )+
geom_line(aes(y = Sim, color = "Simulation"), size = 1, linetype = "dashed")+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
facet_wrap(~ Loc, ncol = 1, scales = "free_y")+
theme_bw()+
scale_color_manual(values = c('blue', 'black'), name = NULL) +
scale_fill_manual(values = 'grey30', name = NULL)
There are a number of valid ways to approach this, but this is how many people do it.

ggplot2: Adjust legend symbols in overlayed plot

I need to create a plot, in which a histogram gets overlayed by a density. Here is my result so far using some example data:
library("ggplot2")
set.seed(1234)
a <- round(rnorm(10000, 5, 5), 0)
b <- rnorm(10000, 5, 7)
df <- data.frame(a, b)
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., col = "histogram", linetype = "histogram"), fill = "blue") +
stat_density(aes(x = b, y = ..density.., col = "density", linetype = "density"), geom = "line") +
scale_color_manual(values = c("red", "white"),
breaks = c("density", "histogram")) +
scale_linetype_manual(values = c("solid", "solid")) +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.text = element_text(size = 15))
Unfortunately I can not figure out how I can change the symbols in the legend properly. The first symbol should be a relatively thick red line and the second symbol should be a blue box without the white line in the middle.
Based on some internet research, I tried to change different things in scale_linetype_manual and further I tried to use override.aes, but I could not figure out how I would have to use it in this specific case.
EDIT - Here is the best solution based on the very helpful answers below.
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., linetype = "histogram"),
fill = "blue",
# I added the following 2 lines to keep the white colour arround the histogram.
col = "white") +
scale_linetype_manual(values = c("solid", "solid")) +
stat_density(aes(x = b, y = ..density.., linetype = "density"),
geom = "line", color = "red") +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.text = element_text(size = 15),
legend.key = element_blank()) +
guides(linetype = guide_legend(override.aes = list(linetype = c(1, 0),
fill = c("white", "blue"),
size = c(1.5, 1.5))))
As you thought, most of the work can be done via override.aes for linetype.
Note I removed color from the aes of both layers to avoid some trouble I was having with the legend box outline. Doing this also avoids the need for the scale_*_* function calls. To set the color of the density line I used color outside of aes.
In override.aes I set the linetype to be solid or blank, the fill to be either white or blue, and the size to be 2 or 0 for the density box and histogram box, respectively.
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., linetype = "histogram"), fill = "blue") +
stat_density(aes(x = b, y = ..density.., linetype = "density"), geom = "line", color = "red") +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.text = element_text(size = 15),
legend.key = element_blank()) +
guides(linetype = guide_legend(override.aes = list(linetype = c(1, 0),
fill = c("white", "blue"),
size = c(2, 0))))
The fill and colour aesthetics are labelled by histogram and density respectively, and their values set using scale_*_manual. Doing so maps directly to the desired legend without needing any overrides.
ggplot(df) +
geom_histogram(aes(x = a, y = ..density.., fill = "histogram")) +
stat_density(aes(x = b, y = ..density.., colour="density"), geom = "line") +
scale_fill_manual(values = c("blue")) +
scale_colour_manual(values = c("red")) +
labs(fill="", colour="") +
theme(legend.title = element_blank(),
legend.position = c(.75, .75),
legend.box.just = "left",
legend.background = element_rect(fill=NULL),
legend.key = element_rect(fill=NULL),
legend.text = element_text(size = 15))

Adding an additional point to ggplot

This question is a follow-up to this post: previous post
I have 28 variables, M1, M2, ..., M28, for which I compute certain statistics x and y.
library(ggplot2)
df = data.frame(model = factor(paste("M", 1:28, sep = ""), levels=paste("M", 1:28, sep = "")), a = runif(28, 1, 1.05), b = runif(28, 1, 1.05))
levels = seq(0.8, 1.2, 0.05)
Here is the plot:
ggplot(data=df) +
geom_polygon(aes(x=model, y=a, group=1), color = "black", fill = NA) +
geom_polygon(aes(x=model, y=b, group=1), color = "blue", fill = NA) +
coord_polar() +
scale_y_continuous(limits=range(levels), breaks=levels, labels=levels) +
theme(axis.text.y = element_blank(), axis.ticks = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank())
I would like to add a point the the plot, with y-value = 1 for M1 (model1). I tried adding:
geom_point(aes(y = 1, x = "M1"), color = "red", cex = 0.5)
but it doesn't work. Any idea what I am doing wrong?
Thanks for your help!
cex is not an argument for geom_point. Try size, e.g.
geom_point(aes(y = 1, x = "M1"), color = "red", size = 10)

Resources