ggplot2 add manual legend for two data series - r

I have this dataframe:
Control Stress days sd_control sd_stress
X1 0.9702100 0.9343627 X1 0.001900535 0.07035645
X2 0.9666619 0.8595523 X2 0.014946893 0.04066567
X3 0.9165654 0.7160598 X3 0.072655343 0.07025344
X4 0.9208237 0.6668044 X4 0.050870831 0.08736982
X5 0.8766547 0.7660685 X5 0.073588197 0.04868614
X6 0.9599553 0.7937444 X6 0.041559836 0.05326769
X7 0.9736297 0.8188934 X7 0.003817743 0.06272428
and based on this data I've done this plot:
With the following code:
significance <- data.frame(days=c("X2","X3","X4","X6"),value=c(1.02,1.02,1.02,1.02))
ggplot(my_data, aes(x=days,y=Control,group=1)) +
geom_errorbar(aes(ymax = Control-sd_control, ymin = Control+sd_control),
width=0.2, size=0.5) +
geom_errorbar(aes(ymax = Stress-sd_stress, ymin = Stress+sd_stress),
width=0.2, size=0.5) +
geom_point(shape=23,color='gray45',fill='gray45',size=4) +
geom_line(color='gray45',size=1) +
geom_point(data=my_data,aes(x=days,y=Stress),size=4,shape=22,fill='gray',color='gray',
show.legend = TRUE) +
geom_line(data = my_data, aes(x=days,y=Stress),color='gray',size=1) +
geom_point(data=significance, aes(x=days,y=value),shape='*',size=6) +
labs(x='\nDAT',y='RWC\n') +
scale_y_continuous(labels = percent_format(accuracy = 1),limits = c(0.5,1.04),
expand = c(0,0), breaks = seq(from=0.5,to=1,by=0.05)) +
scale_x_discrete(expand = c(0.07, 0),labels = c(0,7,14,21,27,35,42)) +
ggtitle('Relative Water Content\n') +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5),
panel.background = element_rect(fill = 'white'),
plot.title = element_text(hjust = 0.5,family = 'Calibri',face='bold'),
axis.title = element_text(family = 'Calibri',face = 'bold'),
axis.text = element_text(family = 'Calibri')
)
I want to add a legend in the bottom-right on the plot that describres the Control and Stress Treatmentes with the same shape of the points. I've tried several approaches that I've found here as set a color vector and scale_colour_manual attributes but none of them worked. Any suggestion?

The issue is that you use the color, fill and shape arguments.
To get a legend you have to map on aesthetics, i.e. inside aes().
After doing so ggplot will add lgends(s) automatically and you can apply scale_xxx_manual to get the desired colors, fill and shapes.
However, as this results in 3 legends (was not able to figure out why the merging of the legends failed) I use guides to keep only one of them and guide_legend to style the legend. Try this:
library(ggplot2)
library(scales)
ggplot(my_data, aes(x=days, group=1)) +
geom_errorbar(aes(ymax = Control-sd_control, ymin = Control+sd_control),
width=0.2, size=0.5) +
geom_errorbar(aes(ymax = Stress-sd_stress, ymin = Stress+sd_stress),
width=0.2, size=0.5) +
geom_point(aes(y=Control, color = "Control", fill = "Control", shape = "Control"), size=4) +
geom_line(aes(y=Control, color = "Control"),size=1) +
geom_point(aes(y=Stress, color = "Stress", fill = "Stress", shape = "Stress"), size=4) +
geom_line(aes(y=Stress, color = "Stress"), size=1) +
geom_point(data=significance, aes(y=value),shape='*',size=6) +
scale_color_manual(values = c("Control" = 'gray45', "Stress" = 'gray') ) +
scale_fill_manual(values = c("Control" = 'gray45', "Stress" = 'gray') ) +
scale_shape_manual(values = c("Control" = 23, "Stress" = 22)) +
guides(shape = FALSE, fill = FALSE,
color = guide_legend(override.aes = list(shape = c("Control" = 23, "Stress" = 22),
fill = c("Control" = 'gray45', "Stress" = 'gray')))) +
labs(x='\nDAT',y='RWC\n') +
scale_y_continuous(labels = percent_format(accuracy = 1),limits = c(0.5,1.04),
expand = c(0,0), breaks = seq(from=0.5,to=1,by=0.05)) +
scale_x_discrete(expand = c(0.07, 0), labels = c(0,7,14,21,27,35,42)) +
ggtitle('Relative Water Content\n') +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5),
panel.background = element_rect(fill = 'white'),
plot.title = element_text(hjust = 0.5,family = 'Calibri',face='bold'),
axis.title = element_text(family = 'Calibri',face = 'bold'),
axis.text = element_text(family = 'Calibri')
)

Related

ggplot2 Delete elements from legend

I have this plot:
that was made based on this data:
days variable value sd
1 X1 Control 75.03424 3.857730
2 X2 Control 70.17851 2.913420
3 X3 Control 65.01627 9.188947
4 X4 Control 65.70995 10.882072
5 X5 Control 56.98791 8.070014
6 X6 Control 56.64376 4.827183
7 X1 Stress 75.63113 3.207749
8 X2 Stress 70.56030 5.626266
9 X3 Stress 61.56402 7.078610
10 X4 Stress 48.04541 15.287234
11 X5 Stress 43.54458 8.148382
12 X6 Stress 37.51121 9.494008
With this code:
significance <- data.frame(days=c("X4","X5","X6"),value=c(82,70,67), variable=NA)
# Plot
library(ggplot2)
library(extrafont)
library(scales)
library(Cairo)
ggplot(my_mean, aes(x=days, y=value, fill=variable)) +
geom_bar(stat='identity', position='dodge', width = 0.75) +
geom_errorbar(aes(ymin = value-sd, ymax = value+sd),
position = position_dodge(0.75),
width = 0.3) +
labs(x='\nDAT',y='μg/cm2\n') +
scale_y_continuous(limits = c(0,90), expand = c(0,0),
breaks = seq(from=0,to=90,by=10)) +
scale_x_discrete(labels = c(0,7,14,21,27,35)) +
ggtitle('Chlorophyll Content\n') +
geom_point(data=significance, aes(y=value),shape='*',size=6) +
scale_color_manual(values = c("Control" = 'gray45', "Stress" = 'gray')) +
scale_fill_manual(values = c("Control" = 'gray45', "Stress" = 'gray')) +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5),
panel.background = element_rect(fill = 'white'),
plot.title = element_text(hjust = 0.5,family = 'Calibri',face='bold'),
axis.title = element_text(family = 'Calibri',face = 'bold'),
axis.text = element_text(family = 'Calibri'),
legend.text = element_text(family = 'Calibri',face = 'bold'),
legend.position = c(0.92, 0.91),
legend.key = element_rect(fill = NA,color = NA),
legend.title = element_blank(),
legend.background = element_blank()
)
Note how I made a dataframe to map my significance points in the plot. But for some reason, these points also were added to the legend, and don't want this to happens. I suspect this could be fixed with some legend function inside the theme configurations, but I wasn't able to find which function to use and what arguments does it would have.
Any suggestion? Or maybe a better approach to map my significance "stars"?
If you don't want the stars to appear in the legend, try geom_point(..., show.legend = F). In fact, show.legend = F is an option in many ggplot2 layers.
You can try this:
ggplot(my_mean, aes(x=days, y=value, fill=variable)) +
geom_bar(stat='identity', position='dodge', width = 0.75) +
geom_errorbar(aes(ymin = value-sd, ymax = value+sd),
position = position_dodge(0.75),
width = 0.3,color='black') +
labs(x='\nDAT',y='μg/cm2\n') +
scale_y_continuous(limits = c(0,90), expand = c(0,0),
breaks = seq(from=0,to=90,by=10)) +
scale_x_discrete(labels = c(0,7,14,21,27,35)) +
ggtitle('Chlorophyll Content\n') +
geom_point(data=significance, aes(y=value),shape='*',size=6,color='black') +
scale_color_manual(values = c("Control" = 'gray45', "Stress" = 'gray')) +
scale_fill_manual(values = c("Control" = 'gray45', "Stress" = 'gray')) +
guides(fill=guide_legend(override.aes=list(shape=NA)))+
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5),
panel.background = element_rect(fill = 'white'),
plot.title = element_text(hjust = 0.5,family = 'Calibri',face='bold'),
axis.title = element_text(family = 'Calibri',face = 'bold'),
axis.text = element_text(family = 'Calibri'),
legend.text = element_text(family = 'Calibri',face = 'bold'),
legend.position = c(0.92, 0.91),
legend.key = element_rect(fill = NA,color = NA),
legend.title = element_blank(),
legend.background = element_blank()
)

ggplot2 How to put at bottom the x axis title?

I have this dataframe:
Control Stress days sd_control sd_stress
X1 -0.2866667 -0.2833333 X1 0.11846237 0.05773503
X2 -0.2566667 -1.0333333 X2 0.08144528 0.15275252
X3 -0.4766667 -1.4500000 X3 0.09291573 0.10000000
X4 -0.4900000 -1.2766667 X4 0.21517435 0.22501852
X5 -0.4600000 -1.2666667 X5 0.07549834 0.40722639
X6 -0.2633333 -1.0833333 X6 0.12662280 0.10408330
X7 -0.2833333 -1.0333333 X7 0.03511885 0.07767453
Based on this data I made this plot:
with this code:
ggplot(data = my_mean, aes(x=days,group=1)) +
geom_errorbar(aes(ymax = Control-sd_control, ymin = Control+sd_control),
width=0.2, size=0.5) +
geom_errorbar(aes(ymax = Stress-sd_stress, ymin = Stress+sd_stress),
width=0.2, size=0.5) +
geom_point(aes(y=Control, color = "Control", fill = "Control", shape = "Control"),
size=4) +
geom_line(aes(y=Control, color = "Control"),size=1) +
geom_point(aes(y=Stress, color = "Stress", fill = "Stress", shape = "Stress"),
size=4) +
geom_line(aes(y=Stress, color = "Stress"), size=1) +
geom_point(data=significance, aes(y=value),shape='*',size=6) +
scale_color_manual(values = c("Control" = 'gray45', "Stress" = 'gray') ) +
scale_fill_manual(values = c("Control" = 'gray45', "Stress" = 'gray') ) +
scale_shape_manual(values = c("Control" = 23, "Stress" = 22)) +
guides(shape = FALSE, fill = FALSE,
color = guide_legend(override.aes = list(shape = c("Control" = 23,
"Stress" = 22),
fill = c("Control" = 'gray45',
"Stress" = 'gray')))) +
labs(x='\nDAT',y='ΨMpa\n') +
scale_y_continuous(limits = c(-2,-0), expand = c(0,0),
breaks = seq(from=0,to=-2.5,by=-0.2)) +
scale_x_discrete(expand = c(0.07, 0), labels = c(0,7,14,21,27,35,42),
position = "top") +
ggtitle('Leaf Water Potential\n') +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5),
panel.background = element_rect(fill = 'white'),
plot.title = element_text(hjust = 0.5,family = 'Calibri',face='bold'),
axis.title = element_text(family = 'Calibri',face = 'bold',
axis.title.x.bottom =TRUE),
axis.text = element_text(family = 'Calibri'),
legend.text = element_text(family = 'Calibri',face = 'bold'),
legend.title = element_blank(),
legend.position = c(0.9, 0.13),
legend.key = element_rect(fill = NA,color = NA)
)
Note how I included the position="top" argument in scale_x_discrete because I want the axis text to appear on top, but I want the axis title ("DAT") back on the bottom. I guess the axis.title.x.bottom theme function could do the trick but I was unable to find how to pass it to the code and what arguments does it need. Any suggestions with that?
I think the best way is to use a secondary axis without an axis title scale_x_continuous(sec.axis = dup_axis(name =''), breaks=c(0,7,14, 21, 28, 35, 42), labels=c('0','7','14', '21', '28', '35', '42')) and to switch the text of the x-axis of: axis.text.x.bottom = element_blank().
I used scale_x_continuous and changed days by df$days <- seq(0, 42, 7) .
If you want, you can switch the ticks on the bottom x-axis off, too.
library(ggplot2)
df <- read.table(text="Control Stress days sd_control sd_stress
-0.2866667 -0.2833333 X1 0.11846237 0.05773503
-0.2566667 -1.0333333 X2 0.08144528 0.15275252
-0.4766667 -1.4500000 X3 0.09291573 0.10000000
-0.4900000 -1.2766667 X4 0.21517435 0.22501852
-0.4600000 -1.2666667 X5 0.07549834 0.40722639
-0.2633333 -1.0833333 X6 0.12662280 0.10408330
-0.2833333 -1.0333333 X7 0.03511885 0.07767453", header=T)
df$days <- seq(0,42,7)
ggplot(data = df, aes(x=days,group=1)) +
geom_errorbar(aes(ymax = Control-sd_control, ymin = Control+sd_control),
width=0.2, size=0.5) +
geom_errorbar(aes(ymax = Stress-sd_stress, ymin = Stress+sd_stress),
width=0.2, size=0.5) +
geom_point(aes(y=Control, color = "Control", fill = "Control", shape = "Control"),
size=4) +
geom_line(aes(y=Control, color = "Control"),size=1) +
geom_point(aes(y=Stress, color = "Stress", fill = "Stress", shape = "Stress"),
size=4) +
geom_line(aes(y=Stress, color = "Stress"), size=1) +
#geom_point(data=significance, aes(y=value),shape='*',size=6) +
scale_color_manual(values = c("Control" = 'gray45', "Stress" = 'gray') ) +
scale_fill_manual(values = c("Control" = 'gray45', "Stress" = 'gray') ) +
scale_shape_manual(values = c("Control" = 23, "Stress" = 22)) +
guides(shape = FALSE, fill = FALSE,
color = guide_legend(override.aes = list(shape = c("Control" = 23,
"Stress" = 22),
fill = c("Control" = 'gray45',
"Stress" = 'gray')))) +
labs(x='\nDAT',y='ΨMpa\n') +
scale_y_continuous(limits = c(-2,-0), expand = c(0,0),
breaks = seq(from=0,to=-2.5,by=-0.2)) +
#scale_x_discrete(expand = c(0.07, 0), labels = c(0,7,14,21,27,35,42)) +
scale_x_continuous(sec.axis = dup_axis(name =''),
breaks=c(0,7,14, 21, 28, 35, 42),
labels=c('0','7','14', '21', '28', '35', '42')) +
ggtitle('Leaf Water Potential\n') +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5),
panel.background = element_rect(fill = 'white'),
plot.title = element_text(hjust = 0.5,family = 'Calibri',face='bold'),
#axis.title.x.bottom = element_blank(),
axis.text.x.bottom = element_blank(),
#axis.title = element_text(axis.title.x.bottom =TRUE),
#axis.text = element_text(family = 'Calibri'),
legend.text = element_text(family = 'Calibri',face = 'bold'),
legend.title = element_blank(),
legend.position = c(0.9, 0.13),
legend.key = element_rect(fill = NA,color = NA)
)
PS: I switched the third data line singificance off; don't know where it comes from
What you could do is simulate an x-axis title at the bottom using a caption, then just remove the one at the top. These additions do the trick:
ggplot() +
... +
labs(caption = "DAT") +
theme(axis.title.x = element_blank(),
plot.caption = element_text(size = 14, hjust = 0.5, face = "bold"),
...)
This is what it should look like:

How to draw three differents non-linear regression with ggplot2

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)

Change aestesics in ggplot2 barplot

How to modify the "New infected", "Mortality" and "TDR level" text characteristics? I want to make it bigger and in bold. How to modify the "Scen1", "Scen2" and "Scen3" text?
I already looked into the R documentation but didn't find an answer in the particular case where barplot are used with "dodge".
Here is the code:
myd<- data.frame( var1 = rep(c("Newly infected","Mortality","TDR level"),each=3),
samp = rep(c("Scen1","Scen2","Scen3"),3),
V3 = c(3.5,2,NA,8,2,NA,4,5,NA)/1.5, V2 = c(3.5,2,NA,8,3,NA,4,4.3,NA), V1 = c(1.5,0.2,5,5,3,0.2,4,-5,2) )
# rshaping data to long form for ggplot2
library(reshape2)
meltd<- melt(myd, id.vars=1:2)
#meltd<- meltd[-which(is.na(meltd$value)),]
ggplot(meltd, aes(x = var1, y = value, fill = variable, label = paste0(round(value * 100, 1), "%"))) +
geom_bar(stat = "identity", position = position_dodge(width = 0.6), width = 0.5) +
facet_grid(samp ~ ., switch = "y", scales = "free_y", space = "free") +
coord_flip() +
scale_fill_manual("legend",values = c("V3" = "orange", "V2" = "red", "V1" = "blue", "Baseline" = "black")) +
geom_text(aes(y = value + 0.4 * sign(value)), position = position_dodge(width = 0.6)) +
theme_bw() +
theme(
legend.position = "none",
strip.placement = "outside",
#axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.y = element_text(colour="black"),
strip.text.y = element_text(size = 12, colour = "black"))+
ylab("Relative change (in %)")
Here is the plot:
You're pretty much there, I just added face, and size arguments:
axis.text.y = element_text(colour="black", face='bold',size=12),
strip.text.y = element_text(size = 12, colour = "black", face='bold'))+
ylab("Relative change (in %)")
Or to change the size of the value labels add size to geom_text:
geom_text(aes(y = value + 0.4 * sign(value)),
position = position_dodge(width = 0.6), size=6)
Full code:
ggplot(meltd, aes(x = var1, y = value, fill = variable, label = paste0(round(value * 100, 1), "%"))) +
geom_bar(stat = "identity", position = position_dodge(width = 0.6), width = 0.5) +
facet_grid(samp ~ ., switch = "y", scales = "free_y", space = "free") +
coord_flip() +
scale_fill_manual("legend",values = c("V3" = "orange", "V2" = "red", "V1" = "blue", "Baseline" = "black")) +
geom_text(aes(y = value + 0.4 * sign(value)), position = position_dodge(width = 0.6), size=6)+
theme_bw() +
theme(
legend.position = "none",
strip.placement = "outside",
#axis.title.x = element_blank(),
axis.title.y = element_blank(),
# added face and size arguments
axis.text.y = element_text(colour="black", face='bold',size=12),
strip.text.y = element_text(size = 12, colour = "black", face='bold'))+
ylab("Relative change (in %)")

Layout of plots with a unique legend using ggplot

I was trying to create a layout with plots sharing the same legend. The legend is on the top of the first plot, however, the next plot has a different scale. How can I solve this?
library(ggplot2)
library(gridExtra)
grid.arrange(
ggplot(mpg, aes(displ, cty)) +
geom_point(aes(shape = "Data")) +
stat_smooth(aes(linetype = "Regression"), method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
scale_shape_manual(values = 1) +
labs(shape = "", linetype = "") +
theme_classic() +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10),
legend.position = "top")
,
ggplot(mpg, aes(displ, cty)) +
geom_point(shape = 1) +
stat_smooth(method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
theme_classic() +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10))
)
If the plots also have the same axes labels, facet_wrap may be a good option.
library(ggplot2)
data = rbind(data.frame("id" = 1, mpg), data.frame("id" = 2, mpg))
ggplot(data, aes(displ, cty)) +
geom_point(aes(shape = "Data")) +
stat_smooth(aes(linetype = "Regression"), method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
scale_shape_manual(values = 1) +
labs(shape = "", linetype = "") +
theme_classic() +
facet_wrap(~id, ncol = 1 ) +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10),
legend.position = "top",
strip.background = element_blank(),
strip.text.x = element_blank()) #these two lines remove the facet strips
grid.arrange doesn't try to align plot panels; it's a generic function meant for all kinds of grid graphics, and in this case since the top plot has a legend it gets shrunk to fit in the available space (by default 1/2 of the page here). For the specific case of ggplots I would use egg::ggarrange,
library(ggplot2)
library(egg)
ggarrange(
ggplot(mpg, aes(displ, cty)) +
geom_point(aes(shape = "Data")) +
stat_smooth(aes(linetype = "Regression"), method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
scale_shape_manual(values = 1) +
labs(shape = "", linetype = "") +
theme_classic() +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10),
legend.position = "top")
,
ggplot(mpg, aes(displ, cty)) +
geom_point(shape = 1) +
stat_smooth(method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
theme_classic() +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10))
)
I don't know how to use grid.arrange, but here's a solution using my cowplot package. The idea is to separate the legend out from the plot and then put the three elements into one column. A similar approach would work with grid.arrange, I assume.
library(cowplot)
p1 <- ggplot(mpg, aes(displ, cty)) +
geom_point(aes(shape = "Data")) +
stat_smooth(aes(linetype = "Regression"), method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
scale_shape_manual(values = 1) +
labs(shape = "", linetype = "") +
theme_classic() +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10),
legend.position = "top")
p2 <- ggplot(mpg, aes(displ, cty)) +
geom_point(shape = 1) +
stat_smooth(method = "lm",
formula = y ~ x, se = FALSE, colour = 1, size = 0.5) +
theme_classic() +
theme(panel.border = element_rect(colour = "black", fill=NA, size = 0.5),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 10))
legend <- get_legend(p1)
plot_grid(legend, p1 + theme(legend.position = "none"), p2,
ncol=1, rel_heights = c(0.1, 1, 1))

Resources