I aranged a set of R plots into one using ggarange, How can I label them A,B and C at the top left of each subplot?
Code:
library(ggplot2)
library(ggpubr)
# default ggplot2 theme
P1 <- ggplot(iris, aes(Sepal.Length, Petal.Width, color = Species)) +
geom_point()
P2 <- ggplot(iris, aes(Sepal.Length, Sepal.Width, color = Species)) +
geom_point()
P3 <- ggplot(iris, aes(Petal.Length, Sepal.Width, color = Species)) +
geom_point()
ggarrange(P1, P2, P3, ncol=3, nrow=1, common.legend = TRUE, legend="bottom")
Use labels:
ggarrange(P1, P2, P3, labels = c("A", "B", "C"),
ncol = 3, nrow = 1,
common.legend = TRUE, legend = "bottom")
Related
I am writing R ggplot, and I am arranging multiple plots with grid.arrange.
Is there a way to add some words in in between two plots?
I want the output to be like the red word.
Thank you for your help :)
library(ggplot2)
library(gridExtra)
P1 <- ggplot(mtcars, aes(x = mpg)) +
geom_histogram()
P2 <- ggplot(mtcars, aes(x = wt)) +
geom_histogram()
grid.arrange(P1, *I want to add some information here*,P2, ncol = 1, nrow = 2)
You could use the grid.text function from grid library as follows
### Libraries
library(grid)
library(ggplot2)
library(gridExtra)
### Data
data(cars)
### Initiating plots
P1 <- ggplot(mtcars, aes(x = mpg)) +
geom_histogram()
P2 <- ggplot(mtcars, aes(x = wt)) +
geom_histogram()
### Display plots
grid.arrange(P1, P2, ncol = 1, nrow = 2)+
grid.text("I want to add some information here",
x=unit(0.25, "npc"),
y=unit(.52, "npc"),
gp=gpar(fontsize=20, col="red"))
One approach would be to create another ggplot with only text that you want and use it in cowplot::plot_grid
library(ggplot2)
P1 <- ggplot(mtcars, aes(x = mpg)) + geom_histogram()
P2 <- ggplot() +
annotate("text", x = 4, y = 25, size=8,
label = "This is some text in the middle", color = "red") +
theme_void()
P3 <- ggplot(mtcars, aes(x = wt)) + geom_histogram()
cowplot::plot_grid(P1, P2, P3, rel_heights = c(1/2, 1/12, 1/2),
align = "v", nrow = 3)
I need to arrange multiple plots with common legend in a single page and used following code:
library(ggpubr)
ggarrange(fig1, fig2, fig3, nrow=2, ncol=2, common.legend = TRUE, legend="right")
Now, I'm wondering if there are other packages/ways where I can customize position of the common legend since the 'ggarrange' has only 'top', 'bottom', 'right', 'left' and 'none' options for this. Since second row and second column is empty, I want the legend be appeared there.
Perhaps the cowplot package will work?
Minimal Reproducible Example:
library(tidyverse)
library(ggpubr)
fig1 <- ggplot(mtcars, aes(x = hp, y = mpg)) +
geom_point()
fig2 <- ggplot(mtcars, aes(x = cyl, y = mpg, group = cyl, fill = factor(cyl))) +
geom_boxplot() +
scale_fill_viridis_d()
fig3 <- ggplot(mtcars, aes(x = disp, y = mpg)) +
geom_point()
ggarrange(fig1, fig2, fig3, nrow=2, ncol=2, common.legend = TRUE, legend="right")
Using the cowplot package:
library(cowplot)
legend <- get_legend(fig2)
fig2_no_legend <- ggplot(mtcars, aes(x = cyl, y = mpg, group = cyl, fill = factor(cyl))) +
geom_boxplot() +
scale_fill_viridis_d() +
theme(legend.position = "none")
cowplot::plot_grid(fig1, fig2_no_legend, fig3, legend, nrow = 2, ncol = 2)
I have a function that returns a patchwork plot and I can't make any changes to. I would like to add a rectGrob() on top of it. When I try to do this I remove two of the plots.
library(gridExtra)
library(patchwork)
library(ggplot2)
p1 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point()
p2 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) + geom_point()
p3 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width), col = 'blue') + geom_point()
p <- p1 + p2 + p3
grob_top <- grobTree(rectGrob(gp=gpar(fill='#F0F0F0',col= 'black')), textGrob('P1,P2, P3'))
grid.arrange(grob_top, p, heights = c(0.1, 0.9))
Using patchwork::wrap_elements() works better than gridExtra::grid.arrange()
patchwork::wrap_elements(grob_top) /
patchwork::wrap_elements(p) /
patchwork::wrap_elements(p) +
patchwork::plot_layout(ncol = 1, heights = c(0.1, 0.45, 0.45))
I think you want:
grid.arrange(grob_top,
p,
nrow = 2,
heights = c(0.1, 0.9))
I'm working with 4 different plots and I'm using ggarrange() from the ggpubr-package to put them in a single plot. I've prepared an example:
library(ggpubr)
library(ggplot2)
p1 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point() + ggtitle("Plot 1")
p2 <- ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) + geom_point() + ggtitle("Plot 2")
p3 <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Width)) + geom_point() + ggtitle("Plot 3")
p4 <- ggplot(iris, aes(x = Petal.Length, y = Sepal.Width)) + geom_point() + ggtitle("Plot 4") +
facet_wrap(~Species)
plot.list <- list(p1, p2, p3, p4)
ggarrange(plotlist = plot.list)
Output:
I would like to draw a border around the single plots, like so:
Is there any way to draw this border? Thanks!
grid.polygon() is quite manual but I think it can do the trick:
Using RStudio
library("ggpubr")
library(ggplot2)
library(gridExtra)
library(grid)
p1 <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point() + ggtitle("Plot 1")
p2 <- ggplot(iris, aes(x = Petal.Length, y = Petal.Width)) + geom_point() + ggtitle("Plot 2")
p3 <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Width)) + geom_point() + ggtitle("Plot 3")
p4 <- ggplot(iris, aes(x = Petal.Length, y = Sepal.Width)) + geom_point() + ggtitle("Plot 4") +
facet_wrap(~Species)
plot.list <- list(p1, p2, p3, p4)
ggarrange(plotlist = plot.list)
x = c(0, 0.5, 1, 0.5, 0.5, 0.5)
y = c(0.5, 0.5, 0.5,0, 0.5, 1)
id = c(1,1,1,2,2,2)
grid.polygon(x,y,id)
Using Shiny (Edit)
When doing it within a shiny-app, ones needs to add the grid using annotation_custom(), as follows:
ggarrange(plotlist = plot.list) +
annotation_custom(
grid.polygon(c(0, 0.5, 1, 0.5, 0.5, 0.5),
c(0.5, 0.5, 0.5,0, 0.5, 1),
id = c(1,1,1,2,2,2),
gp = gpar(lwd = 1.5)))
Not sure if this will work for you, but you can just put borders around your individual plots. However, this includes borders on the outside of the layout. Your description seems like you're not opposed to that, but there are only inner gridlines in your example plot.
You could add the theme call when you create the plots; rather than editing the plot creation, I just did it to each plot in the list before sticking them all together.
library(ggpubr)
library(ggplot2)
#### same plot creation here ######
plot.list <- lapply(list(p1, p2, p3, p4),
function(p) p + theme(plot.background = element_rect(color = "black")))
ggarrange(plotlist = plot.list)
I have three plots p1, p2 and p3.
I would like to combine p2 and p3 and add the legends of p2 and p1 on the right side above each other. In the following example the legends are identical. In the real data they are differend.
I use ggplot2 and cowplot
# plot 1
p1 <- ggplot(iris, aes(Sepal.Length, fill = Species)) +
geom_density(alpha = .7)
# plot 2
p2 <- ggplot(iris, aes(Sepal.Width, fill = Species)) +
geom_density(alpha = .7)
# plot 3
p3 <- ggplot(iris, aes(Petal.Width, fill = Species)) +
geom_density(alpha = .7)
# legend1
legend1 <- get_legend(p1)
# legend2
legend2 <- get_legend(p2)
# combine plots
prow <- plot_grid( p2 + theme(legend.position="none"),
p3 + theme(legend.position="none"),
align = 'vh',
labels = c("a", "b"),
hjust = -1,
nrow = 1,
axis="1"
)
prow
# add legend1
p <- plot_grid( prow, legend1, rel_widths = c(1, .3))
p
# add legend2
plot_grid(p, legend2, rel_widths =c(1, .3))
This gives me this:
What I try to get is:
I tried to solve the problem using
+ theme(legend.position=c()
and
+ theme(legend.justification = "top"))
however, I could not get the desired plot.
You're actually very close. You can use ggdraw to achieve what you want. See ?get_legend for another example of this.
# combine plots
prow <- ggdraw(
plot_grid(
plot_grid(p2 + theme(legend.position="none") ,
p3 +theme(legend.position="none"),
align = 'vh',
labels = c("a", "b"),
hjust = -1,
nrow = 1,
axis="1"),
# as suggested by aosmith you can add additional columns to make legends appear closer
plot_grid(legend1, legend2,ncol=4),
# I also set the relative widths so the legend takes up less space
nrow=1, rel_widths = c(1,0.2))
)
prow