I have a graph like attached and want to change the 'colour' legend to be a symbol of a square or circle not a line.
ggplot(sharkanovadata, aes(x=mean, y=sd), colour="Sharks")+
geom_point(alpha=0.2)+
geom_point(data=birdanovadata, colour= "#D22B2B", alpha=0.1)+
geom_abline(data=sharkanovadata, mapping=aes(colour="Sharks", slope=0.15, intercept=3.33, linetype= "Genetic"), size=1.2)+
geom_abline(data=sharkanovadata, mapping= aes( colour="Sharks", slope= 0.22, intercept=4.12, linetype= "Imputed"), size=1.2) +
geom_abline(data=birdanovadata, mapping=aes(colour= "Birds", slope=0.17, intercept=0.31, linetype= "Genetic"), size=1.2)+
geom_abline(data=birdanovadata, mapping=aes(colour= "Birds", slope=0.30, intercept=0.53, linetype="Imputed"), size=1.2)+
scale_colour_manual(values= c("Sharks" = "black", "Birds" = "#B03A2E"))+
xlab("Mean ED") +
ylab("Standard deviation of ED") +
ggtitle("Imputed species have a greater linear relationship of standard devation and mean", (size=30))+
theme(panel.background = element_rect(fill = "white"))+
theme(panel.grid.major = element_line(size=0.4, colour= "grey"))+
scale_linetype_manual(values= c("Genetic"= "longdash", "Imputed" = "solid"))+
theme(legend.key.size = unit(1, 'cm')) +
theme(plot.title = element_text(face = "bold"))
As the legend symbols aka key glyphs are determined by the geoms one option would be to switch the key_glyph for one of your geom_ablines. to point which will add a point to each legend. Afterwards we can tweak the the color and linetype legends via the override.aes argument of guide_legend where I opted for a square shape.
As you provided no data I use some fake random data to mimic your real data:
set.seed(123)
birdanovadata <- sharkanovadata <- data.frame(
mean = runif(1000, 0, 150),
sd = runif(1000, 0, 30)
)
library(ggplot2)
ggplot(sharkanovadata, aes(x = mean, y = sd), colour = "Sharks") +
geom_point(alpha = 0.2) +
geom_point(data = birdanovadata, colour = "#D22B2B", alpha = 0.1) +
geom_abline(data = sharkanovadata, mapping = aes(colour = "Sharks", slope = 0.15, intercept = 3.33, linetype = "Genetic"), size = 1.2, key_glyph = "point") +
geom_abline(data = sharkanovadata, mapping = aes(colour = "Sharks", slope = 0.22, intercept = 4.12, linetype = "Imputed"), size = 1.2) +
geom_abline(data = birdanovadata, mapping = aes(colour = "Birds", slope = 0.17, intercept = 0.31, linetype = "Genetic"), size = 1.2) +
geom_abline(data = birdanovadata, mapping = aes(colour = "Birds", slope = 0.30, intercept = 0.53, linetype = "Imputed"), size = 1.2) +
scale_colour_manual(values = c("Sharks" = "black", "Birds" = "#B03A2E")) +
xlab("Mean ED") +
ylab("Standard deviation of ED") +
ggtitle("Imputed species have a greater linear relationship of standard devation and mean", (size <- 30)) +
theme(panel.background = element_rect(fill = "white")) +
theme(panel.grid.major = element_line(size = 0.4, colour = "grey")) +
scale_linetype_manual(values = c("Genetic" = "longdash", "Imputed" = "solid")) +
theme(legend.key.size = unit(1, "cm")) +
theme(plot.title = element_text(face = "bold")) +
guides(color = guide_legend(override.aes = list(linetype = "blank", size = 8, shape = 15)),
linetype = guide_legend(override.aes = list(shape = NA)))
Related
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)
I have a data frame having four columns as shown below (here I just put header of my actual data frame):
df <- tibble(Date=c("2007-05-01", "2007-05-02","2007-05-03", "2007-05-04", "2007-05-05"), Obs = c(0.16,0.15,0.17,0.19,0.14), Sim = c(0.17, 0.11, 0.21, 0.15, 0.13), Rain = c(0.1, 0.11, 0.04,0.21,0.5))
How can I plot the data such that the variables Obs and Sim are plotted on the primary y-axis and Rain is plotted as bars on a reverse secondary axis?
Here is the code I have tried thus far:
ggplot(df, aes(x=as.Date(Date))) +
geom_line(aes(y=Obs, color="red")) +
geom_line(aes(y=Sim, color="green")) +
geom_bar(mapping = aes(y = Rain), stat = "identity") +
scale_y_continuous(name = expression('Soil moisture, m'^"3"*' m'^"-3"),
sec.axis = sec_axis(~ 3 - .*0.5, name = "Precipitation (inch)"))
Here is my expected output:
Edit: Additionally, how can I insert a legend that corresponds to each line (i.e. Obs, Sim, and Rain)?
You can also make two separate plots and stack them on top of each other. This would be useful for people (myself included) who prefer not to use dual-axis plots.
library(tidyverse)
library(lubridate)
library(scales)
df <- tibble(Date = c("2007-05-01", "2007-05-02", "2007-05-03", "2007-05-04", "2007-05-05"),
Obs = c(0.16, 0.15, 0.17, 0.19, 0.14),
Sim = c(0.17, 0.11, 0.21, 0.15, 0.13),
Rain = c(0.10, 0.11, 0.04, 0.21, 0.5))
# convert data to long format
df_long <- df %>%
mutate(Date = as.Date(Date)) %>%
pivot_longer(-Date,
names_to = 'key',
values_to = 'value')
Soil moisture plot
sm1 <- ggplot(data = df_long %>% filter(key != 'Rain'),
aes(x = Date, y = value,
group = key,
shape = key,
linetype = key,
col = key)) +
xlab("") +
ylab(expression('Soil moisture, m'^"3"*' m'^"-3")) +
geom_line(lwd = 0.5) +
geom_point(size = 3, alpha = 0.6) +
scale_color_brewer("", palette = 'Dark2') +
scale_linetype_manual("", values = c(NA, 'solid')) +
scale_shape_manual("", values = c(19, NA)) +
theme_bw(base_size = 16) +
theme(legend.position = "bottom") +
theme(panel.border = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line()) +
theme(axis.title.x = element_blank()) +
theme(legend.key.size = unit(3, 'lines')) +
guides(color = guide_legend(override.aes = list(linetype = c(NA, 1),
alpha = 1.0,
shape = c(19, NA)),
nrow = 1, byrow = TRUE))
Precipitation plot
prec_long <- df_long %>%
filter(key == 'Rain') %>%
rename(Precipitation = matches("Rain"))
maxPrec <- 1.1 * max(prec_long$value, na.rm = TRUE)
p1 <- ggplot(data = prec_long, aes(x = Date, y = value)) +
# use `geom_linerange` to mimic `type = h` in Base R plot
# https://stackoverflow.com/questions/26139878/needle-plot-in-ggplot2
geom_linerange(aes(x = Date,
ymin = 0,
ymax = value),
color = "#2c7fb8",
size = 10) +
xlab("") +
ylab(paste("Precipitation (mm)", sep = "")) +
scale_x_date(position = "top") +
scale_y_reverse(expand = c(0, 0), limits = c(maxPrec, 0)) +
theme_bw(base_size = 16) +
theme(panel.border = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line()) +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
theme(legend.position = "none")
Stack two plots on top of each other
### `cowplot` or `egg` package would work too
# install.packages("patchwork", dependencies = TRUE)
library(patchwork)
p1 / sm1 +
plot_layout(nrow = 2, heights = c(1, 2)) +
plot_annotation(title = "My plot",
subtitle = "Precipitation and Soil moisture")
Created on 2020-07-26 by the reprex package (v0.3.0)
Here's an approach using geom_rect.
Calculate the ratio between the maximum of the primary and secondary axes.
Store the maximum of the secondary reverse axis.
Plot the rectangles using the ymin as the maximum minus the value times the ratio.
Set the secondary axis ticks as the maximum minus the values divided by the ratio.
I added a BottomOffset parameter you could tweak if you want some extra space at the bottom on the secondary axis. I also went ahead and added the code to change the colors of the axes.
Edit: Now with a legend.
Ratio <- max(c(df$Obs, df$Sim), na.rm = TRUE) / max(df$Rain)
RainMax <- max(df$Rain,na.rm = TRUE)
BottomOffset <- 0.05
ggplot(df, aes(x=as.Date(Date))) +
geom_line(aes(y=Obs, color="1")) +
geom_line(aes(y=Sim, color="2")) +
geom_rect(aes(xmin=as.Date(Date) - 0.1,
xmax = as.Date(Date) + 0.1,
ymin = (BottomOffset + RainMax - Rain) * Ratio,
ymax = (BottomOffset + RainMax) * Ratio,
color = "3"),
fill = "red", show.legend=FALSE) +
geom_hline(yintercept = (BottomOffset + RainMax) * Ratio, color = "red") +
geom_hline(yintercept = 0, color = "black") +
labs(x = "Date", color = "Variable") +
scale_y_continuous(name = expression('Soil moisture, m'^"3"*' m'^"-3"),
sec.axis = sec_axis(~ BottomOffset + RainMax - . / Ratio, name = "Precipitation (inch)"),
expand = c(0,0)) +
scale_color_manual(values = c("1" = "blue", "2" = "green", "3" = "red"),
labels = c("1" = "Obs", "2" = "Sim", "3"= "Rain")) +
theme(axis.line.y.right = element_line(color = "red"),
axis.ticks.y.right = element_line(color = "red"),
axis.text.y.right = element_text(color = "red"),
axis.title.y.right = element_text(color = "red"),
axis.line.y.left = element_line(color = "blue"),
axis.ticks.y.left = element_line(color = "blue"),
axis.text.y.left = element_text(color = "blue"),
axis.title.y.left = element_text(color = "blue"),
legend.position = "bottom")
After running the following commands:
Population <- c("A", "A", "A", "A", "B", "B", "B", "B")
Group <- rep(c("Experimental", "Experimental", "Control", "Control"), 2)
wave <- rep(c("Pretest", "Posttest"), 4)
outcome <- c(-.3, -.2, -.3, .4, -.6, -.5, -.6, .6)
ci <- rep(c(.13, .14), 4)
df <- data.frame(Population, Group, wave, outcome, ci)
df$wave <- factor(df$wave,levels = c('Pretest','Posttest'))
library(ggplot2)
pd <- position_dodge(0.1)
ggplot(df, aes(x = wave, y = outcome, color = interaction(Population, Group), shape = Group, group = interaction(Population, Group))) +
geom_errorbar(aes(ymin = outcome - ci, ymax = outcome + ci), width = .25, position = pd, size=.5) +
geom_line(aes(linetype = Group), position = pd, size=1, show.legend = FALSE) +
geom_point(position = pd, size = 3.5, fill = "white", stroke = 1.25, show.legend = FALSE) +
scale_color_manual(values = c("#000000", "#606060", "#000000", "#606060")) +
scale_shape_manual(values = c(23, 21)) +
coord_cartesian(xlim = c(1.4, 1.6), ylim = c(-.91, .91)) +
labs(title = "Outcomes by Population and Study Group", x = "Time", y = "Outcome\nLower scores denote fewer instances", color = "Population and Study Group") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(color = "black"), axis.text.y = element_text(color = "black"), panel.background = element_rect(fill = "#F0F0F0"))
I generate a figure that does not have dots symbols or correct line styles in the legend:
How can I:
add the dots shown in the figure itself into the legend and
have the legend lines reflect that some of dotted lines in the figure?
TYIA.
The simplest way is to create another variable that would reflect the interaction instead of creating it on the fly. If we build the plot step by step, this below gives the dots and errorbars:
library(ggplot2)
pd <- position_dodge(0.1)
df$grp = paste(df$Population,df$Group,sep=".")
g = ggplot(df, aes(x = wave, y = outcome, color = grp, shape = grp))+
geom_errorbar(aes(ymin = outcome - ci, ymax = outcome + ci), width = .25, position = pd, size=.5) +
geom_point(position = pd, size = 3.5, fill = "white", stroke = 1.25) +
scale_color_manual(values = c("#000000", "#000000","#606060", "#606060")) +
scale_shape_manual(values = c(23,21,23,21)) +
coord_cartesian(xlim = c(1.4, 1.6), ylim = c(-.91, .91)) +
labs(title = "Outcomes by Population and Study Group", x = "Time", y = "Outcome\nLower scores denote fewer instances") +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(color = "black"),
axis.text.y = element_text(color = "black"), panel.background = element_rect(fill = "#F0F0F0"))
print(g)
Then add the line while specifying the legend:
g +
geom_line(inherit.aes=FALSE,aes(x = wave, y = outcome,group=grp,linetype=grp)) +
scale_linetype_manual(values=c("solid","dashed","solid","dashed"))
I searched for many questions already answered, but none of them can help me.
This is my code:
ggplot(z, aes(x=`Fecha de muestreo`, y = Valor, color = `Nombre de la estaciĆ³n`)) +
geom_line(size = 0.4) +
geom_point(size=0.5) +
scale_x_date(date_labels = "%b", breaks = "1 month", limits = c(as.Date("2019-1-1"), as.Date("2019-12-20"))) +
scale_y_continuous("pH (unidades de pH)", limits = c(3, 11), breaks = c(3:11)) +
geom_hline(aes(yintercept = 6.5, linetype = "ECA cat.3 inf D1 y D2 : 6.5"), colour = "Blue", size = 0.4)+
geom_hline(aes(yintercept = 8.4, linetype = "ECA cat.3 sup. D1 : 8.4"), colour = "Green", size = 0.4)+
geom_hline(aes(yintercept = 8.5, linetype = "ECA cat.3 sup. D2 : 8.5"), colour = "red", size = 0.4)+
scale_linetype_manual(name = NULL, values = c(1, 1, 1), # values = tipo de lineas
guide = guide_legend(override.aes = list(color = c("blue", "Green", "Red")))) +
theme(axis.text=element_text(size=6),
legend.margin = unit(-0.2, "cm"),
axis.title=element_text(size=7,face="bold")) +
theme(legend.text=element_text(size=6),
legend.title = element_blank(),
legend.spacing.x = unit(.2, 'cm')) +
theme(legend.key = element_rect(fill = "white")) +
theme(panel.background = element_rect(fill = "white")) +
theme(panel.grid = element_line(colour= "gray"))
This is the graph:
I need to change the order of the legends: the "ECAS" should be at the bottom.
How can I do it?
This should be possible using the order term of guides(). For example:
library(ggplot2)
a <- ggplot(mtcars, aes(wt, mpg,
color = as.character(cyl),
fill = as.character(gear))) +
geom_point(size = 5, shape = 21, stroke = 2) +
scale_color_discrete(name = "cyl as color") +
scale_fill_discrete(name = "gear as fill")
a
To reverse the order, we can add: (note, ordering seems to be from the bottom up)
a +
guides(color = guide_legend(order = 0),
fill = guide_legend(order = 1))
I am trying to draw three differents non-linear regression with ggplot2 (like I did with graphpad below (dotted line) (because graphpad can't compare non-linear regression between groups):
So far, I drew this graph:
With the following code:
gp <- ggplot(datapoidsmono, aes(x = time, y = weight)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") +
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white")) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank())
I can't figure out how to draw a non-linear regression for each groups.
The following code did not return any drawn line (no error either):
ggplot(datapoidsmono, aes(time, weight, color = group)) +
geom_point() +
stat_smooth(method = "lm", se=FALSE)
Nor did this one (found here):
ggplot(datapoidsmono, aes(x = time, y = weight, colour=group)) +
stat_smooth(method = 'nls', formula = 'y~a*exp(b*x)') +
stat_smooth(color = 1, method = 'nls', formula = 'y~a*exp(b*x)') +
geom_point(aes(fill=group))
Any idea or clue would be useful to continue! Thanks
Update
As suggested by #PoGibas, I added "group=group" in aes inside first line which worked pefectly to draw the lines!
I tried mulltiple solution to get the perfect fit:
gp + ggplot(aes(group=group))
stat_smooth(method = "lm", formula = y ~ x, size = 1, se = FALSE,colour = "black") +
stat_smooth(method = "lm", formula = y ~ x + I(x^2),size = 1, se = FALSE, colour = "blue") +
stat_smooth(method = "loess", formula = y ~ x, size = 1, se = FALSE, colour = "red") +
stat_smooth(method = "gam", formula = y ~ s(x), size = 1, se = FALSE, colour = "green") +
stat_smooth(method = "gam", formula = y ~ s(x, k = 3), size = 1, se = FALSE, colour = "violet") +
stat_smooth(method = "auto", se=F, colour = "yellow")
But I figured that simply gp + stat_smooth() did perfectly the job (the LOESS method is used).
Now I am trying to change aspect (to a dotted line) and color of the fit...
I tryed gp + stat_smooth(se=F, aes(fill = group)) but now I have another legend box and my lines are always with the same color...
I also tryed to add linetype=group in the aes, but when I use scale_linetype_manual(values=c("dotted", "dotted", "dotted")), every line is dotted (included errorbar)
The complete code is:
ggplot(datapoidsmono, aes(x = time, y = weight, group=group, linetype=group)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") +
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white")) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank()) +
stat_smooth(se=F, aes(fill = group)) +
scale_linetype_manual(values=c("dotted", "dotted", "dotted"))
Thanks to #PoGibas and this post, I added
group=group, color=group in the aes of ggplot and it gave me a good result.
ggplot(datapoidsmono, aes(x = time, y = weight, group=group, color=group)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") +
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white")) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank()) +
stat_smooth(se=F, linetype="dotted")
Here is the final graph:
NB: the fit proposed by graphpad (see first graph) is more stat_smooth(method = "lm", formula = y ~ x + I(x^2),size = 1, se = FALSE) than the one I finally chose (LOESS)