Customize position of common legend in R - r

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)

Related

R adding word in the middle of grid arrange

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)

ggplot2 and grid.arrange, place legend below arranged plots

I am facing a problem when I arrange 2 ggplots next to each other using grid.arrange().
I want to place a legend evenly below both plots.
So I have (pseudocode):
p1 <- ggplot(data = df, aes(group = name, color=as.factor(fac), y = ys, x= (xs))) +
geom_point() +
geom_line() +
theme(legend.position="bottom")
p2 <- ggplot(data = df, aes(group = name, color=as.factor(fac), y = ys, x= (xs))) +
geom_point() +
geom_line() +
grid.arrange(p1,p2, ncol=2, widths=c(0.9,1))
Is there any possibility to arrange the legend so that it is positioned evenly below both plots? If I do it as above, the legend is (logically) placed below the first plot.
With package patchwork you could try this...
library(ggplot2)
library(patchwork)
p1 <- ggplot(data = mtcars, aes(group = gear, color=as.factor(am), y = mpg, x = hp)) +
geom_point() +
geom_line()
p2 <- ggplot(data = mtcars, aes(group = gear, color=as.factor(am), y = mpg, x = hp)) +
geom_point() +
geom_line()
p1 + p2 +
plot_layout(guides = "collect") &
theme(legend.position='bottom')
Created on 2022-02-04 by the reprex package (v2.0.1)

How to create marginal/histogram plot along with a geom_count plot in R?

It seems that, when using a geom_count and then plotting the marginals, it take in account the aggregated dots, but does not consider their size/counts, therefore leading to a wrong marginal.
See bellow the marginal results using geom_count and geom_point.
library(ggplot2)
library(ggExtra)
data(mpg, package="ggplot2")
mpg_select <- mpg[mpg$hwy >= 35 & mpg$cty > 27, ]
g <- ggplot(mpg, aes(cty, hwy)) +
geom_count(show.legend = F)
ggMarginal(g, type = "histogram", fill="transparent")
dev.copy(png,"/tmp/test01.png")
dev.off()
g <- ggplot(mpg, aes(cty, hwy)) +
geom_point()
ggMarginal(g, type = "histogram", fill="transparent")
dev.copy(png,"/tmp/test02.png")
dev.off()
How may I create a geom_count plot and still gets the marginals that would be given if I had used geom_point?
You can do that with cowplot package instead of ggExtra package.
library(tidyverse)
library(cowplot)
g <-
ggplot(mpg, aes(cty, hwy)) +
geom_count(show.legend = F)
xhist <-
axis_canvas(g, axis = "x") +
geom_histogram(data = mpg,
aes(x = cty),
binwidth = 1,
color = 'lightgray')
yhist <-
axis_canvas(g, axis = "y", coord_flip = TRUE) +
geom_histogram(data = mpg,
aes(x = hwy),
binwidth = 1,
color = 'lightgray') +
coord_flip()
g %>%
insert_xaxis_grob(xhist, grid::unit(1, "in"), position = "top") %>%
insert_yaxis_grob(yhist, grid::unit(1, "in"), position = "right") %>%
ggdraw()

How can I align multiple plots by their titles instead of plot area?

I'm using egg to align multiple plots on a page. I'm wondering if it's possible to align two columns by the titles a) and c) instead of plot area? Thanks!
Code:
library(egg)
library(grid)
p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
geom_point() + ggtitle("a)")
p1
p2 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
geom_point() + facet_wrap(~ cyl, ncol = 2, scales = "free") +
guides(colour = "none") +
theme() + ggtitle("b)")
p2
p3 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
geom_point() + facet_grid(. ~ am, scales = "free") + guides(colour="none") +
ggtitle("c)")
p3
g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
g3 <- ggplotGrob(p3)
fg1 <- gtable_frame(g1, debug = TRUE)
fg2 <- gtable_frame(g2, debug = TRUE)
fg12 <- gtable_frame(gtable_rbind(fg1, fg2),
width = unit(2, "null"),
height = unit(1, "null"))
fg3 <-
gtable_frame(
g3,
width = unit(2, "null"),
height = unit(1, "null"),
debug = TRUE
)
grid.newpage()
combined <- gtable_cbind(fg12, fg3)
grid.draw(combined)
Plot:
I found another way by using cowplot package
left_col <- cowplot::plot_grid(p1 + ggtitle(""), p2 + ggtitle(""),
labels = c('a)', 'b)'), label_size = 14,
ncol = 1, align = 'v', axis = 'lr')
cowplot::plot_grid(left_col, p3 + ggtitle(""),
labels = c('', 'c)'), label_size = 14,
align = 'h', axis = 'b')
See also here
Edit:
A recently developed package patchwork for ggplot2 can also get the job done
library(patchwork)
{
p1 + {p2} + patchwork::plot_layout(ncol = 1)
} / p3 + patchwork::plot_layout(ncol = 2)
Adding a blank dummy faceting variable to plot p1/ a) seems like the easiest solution
p1 <- ggplot(data.frame(mtcars, dummy=''),
aes(mpg, wt, colour = factor(cyl))) +
geom_point() + ggtitle("a)") +
facet_wrap(~dummy)

Associate a color palette with ggplot2 theme

I want my ggplot2 theme to use a specific set of colors, but don't see how to avoid a separate line outside of the theme.
I have this data:
library(ggplot2)
mycars <- mtcars
mycars$cyl <- as.factor(mycars$cyl)
And here's a dummy theme I plot with:
mytheme <- theme(panel.grid.major = element_line(size = 2))
ggplot(mycars, aes(x = wt, y = mpg)) +
geom_point(aes(color = cyl)) +
mytheme
I want the point colors to default to my custom palette:
mycolors <- c("deeppink", "chartreuse", "midnightblue")
Can I somehow add that to my ggplot2 theme so that I don't constantly repeat this extra line of code at the end:
ggplot(mycars, aes(x = wt, y = mpg)) +
geom_point(aes(color = cyl)) +
mytheme +
scale_color_manual(values = mycolors)
I tried:
mytheme2 <- mytheme + scale_color_manual(values = mycolors)
But got:
Error: Don't know how to add scale_color_manual(values = mycolors) to
a theme object
Hi you can put your custom element in a list :
# Data
library("ggplot2")
mycars <- mtcars
mycars$cyl <- as.factor(mycars$cyl)
# Custom theme
mytheme <- theme(panel.grid.major = element_line(size = 2))
mycolors <- c("deeppink", "chartreuse", "midnightblue")
# put the elements in a list
mytheme2 <- list(mytheme, scale_color_manual(values = mycolors))
# plot
ggplot(mycars, aes(x = wt, y = mpg)) +
geom_point(aes(color = cyl)) +
mytheme2
I sometimes use this little trick to change colour palettes between plots,
library(ggplot2)
mycars <- mtcars
mycars$cyl <- as.factor(mycars$cyl)
scale_colour_discrete <- function(...) scale_colour_manual(values=palette())
(p <- ggplot(mycars, aes(x = wt, y = mpg)) +
geom_point(aes(color = cyl)) )
palette(c("deeppink", "chartreuse", "midnightblue"))
p
palette(RColorBrewer::brewer.pal(5, "Set1"))
p

Resources