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))
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 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)
I want to add a text to my forest plot in R that has strip in it but the text is repeated on every strip . how can I add only the text to one strip or just on the plot? My code is as below:
My data is like:
Group Mean LowerLimit UpperLimit
M 1.172827 1.083498 1.268857
H 5.142589 4.333141 6.148088
h<-"XXXX"
p = ggplot(data=df4,
aes(x = Group,y = Mean, ymin = LowerLimit, ymax = UpperLimit),
+
ggtitle(PlotTitle)+
geom_point(aes(fill=Group, color=Group), shape=22, size=3)+
geom_pointrange(aes(col=Group), fatten = 3)+
geom_hline(aes(),yintercept =1, linetype="longdash")+
geom_text(aes(-1.5, 0.8, vjust =-0.5, hjust=-0.8, size=10),label=h,
check_overlap = T)+
geom_errorbar(aes(ymin=LowerLimit,
ymax=UpperLimit,col=Group),width=0.4,cex=1)+
facet_wrap(~Group,strip.position="left",nrow=2, scales= "free_y") +
theme(plot.title=element_text(aes(5, 5), hjust=0.5, size=14,face="bold"),
legend.position='none',
strip.text.y = element_text(size=10, hjust=0.5,vjust =1,lineheight=0.1, angle=270,face="bold"),
panel.background = element_blank(),
strip.background = element_rect(fill="green"),
plot.margin = margin(3.5,0.1,3.5, 0.5, "cm"))+
coord_flip()
p
In your parameters for geom_text try changing label=h to label = ''
library(ggplot2)
df4 <- data.frame(Group = c("M", "H"),
Mean = c(1.172827, 5.142589),
LowerLimit = c(1.083498, 4.333141),
UpperLimit = c(1.268857, 6.148088))
PlotTitle = "Insert plot title here"
p = ggplot(data=df4,
aes(x = Group,y = Mean, ymin = LowerLimit, ymax = UpperLimit)) +
ggtitle(PlotTitle) +
geom_point(aes(fill=Group, color=Group), shape=22, size=3) +
geom_pointrange(aes(col=Group), fatten = 3) +
geom_hline(aes(),yintercept =1, linetype="longdash") +
geom_text(aes(-1.5, 0.8, vjust =-0.5, hjust=-0.8, size=10),label='',
check_overlap = T) +
geom_errorbar(aes(ymin=LowerLimit,
ymax=UpperLimit,col=Group),width=0.4,cex=1) +
facet_wrap(~Group,strip.position="left",nrow=2, scales= "free_y") +
theme(plot.title=element_text(aes(5, 5), hjust=0.5, size=14,face="bold"),
legend.position='none',
strip.text.y = element_text(size=10, hjust=0.5,vjust =1,lineheight=0.1, angle=270,face="bold"),
panel.background = element_blank(),
strip.background = element_rect(fill="green"),
plot.margin = margin(3.5,0.1,3.5, 0.5, "cm")) +
coord_flip()
p
which yields this image:
I can create quality control charts with the qicharts2 package.
library(tidyverse)
library(qicharts2)
(plot1 <- qic(age,
data = tail(cabg, 100),
chart = 'i',
ylab = 'Years',
xlab = 'Patient #'
)
)
p1 <- plot1$data
Then I can customize the charts.
(plot2 <- ggplot(p1, aes(x, y)) +
geom_ribbon(ymin = p1$lcl, ymax = p1$ucl, fill = "black", alpha = 0.05) +
geom_line(color = "black", size = 1) +
geom_line(aes(x, cl)) +
geom_point(color = "black" , fill = "black", size = 2) +
geom_point(data = p1 %>% filter(sigma.signal == TRUE), color = "red", size = 2) +
ggtitle(label = NULL) +
labs(x = NULL, y = NULL) +
scale_y_continuous(breaks = seq(0, 100, by = 10)) +
coord_cartesian(ylim = c(0, 100)) +
theme_bw() +
theme(
text = element_text(size = 18),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 0.6),
axis.text.y = NULL,
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text.x = element_text(size = 14, color = "black", angle = 0))
)
Using the part argument, in my qichart, causes it to split at the specified part point(s).
(plot3 <- qic(age,
data = tail(cabg, 100),
chart = 'i',
part = c(70, 85),
ylab = 'Years',
xlab = 'Patient #'
)
)
p3 <- plot3$data
What do I need to add to my customized ggplot2 syntax, below, to get it to part in the same manner? What I've got does everything, EXCEPT, it doesn't part like in the syntax directly above.
(plot4 <- ggplot(p3, aes(x, y)) +
geom_ribbon(ymin = p3$lcl, ymax = p3$ucl, fill = "black", alpha = 0.05) +
geom_line(color = "black", size = 1) +
geom_line(aes(x, cl)) +
geom_point(color = "black" , fill = "black", size = 2) +
geom_point(data = p3 %>% filter(sigma.signal == TRUE), color = "red", size = 2) +
ggtitle(label = NULL) +
labs(x = NULL, y = NULL) +
scale_y_continuous(breaks = seq(0, 100, by = 10)) +
coord_cartesian(ylim = c(0, 100)) +
theme_bw() +
theme(
text = element_text(size = 18),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 0.6),
axis.text.y = NULL,
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text.x = element_text(size = 14, color = "black", angle = 0))
)
Is the following plot what you are looking for?
If so, what I used is group= in the aesthetics of geom_ribbon and geom_line
(plot4 <- ggplot(p3, aes(x, y)) +
geom_ribbon(aes(group=cut(p3$x,c(0,70,85,max(p3$x)))),ymin = p3$lcl, ymax = p3$ucl, fill = "black", alpha = 0.05) +
geom_line(color = "black", size = 1, aes(group=cut(p3$x,c(0,70,85,max(p3$x))))) +
geom_line(aes(x, cl, group=cut(p3$x,c(0,70,85,max(p3$x))))) +
geom_point(color = "black" , fill = "black", size = 2) +
geom_point(data = p3 %>% filter(sigma.signal == TRUE), color = "red", size = 2) +
ggtitle(label = NULL) +
labs(x = NULL, y = NULL) +
scale_y_continuous(breaks = seq(0, 100, by = 10)) +
coord_cartesian(ylim = c(0, 100)) +
theme_bw() +
theme(
text = element_text(size = 18),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 0.6),
axis.text.y = NULL,
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text.x = element_text(size = 14, color = "black", angle = 0)))
I made a scatter plot and then added a regression line. I'm new in ggplot2 and I didn't understand so well how to add a legend. I want a circle like the scater plot saying "data", and a line saying "regression". How can I do this?
library(ggplot2)
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),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 12))
And I want something like:
Custom legends can be tricky to achieve in ggplot as the system is heavily based around "mapping" your data to a scale and then using that to create the legend. For custom legends, you can use an aes() call that manually sets the label you want in the legend, like:
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),
aspect.ratio = 1, axis.text = element_text(colour = 1, size = 12))