Aligning axis and with multiplot axis labels in ggplot2 - r

I am trying to both add multi-plot axis labels and align plots axis in ggplot2.
Here is an example with mtcars data.
library(ggplot2)
library(gridExtra)
#make some plots
c1 <- ggplot(mtcars,aes(mpg,cyl)) + geom_point() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c2 <- ggplot(mtcars,aes(mpg,cyl)) + geom_line() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c3 <- ggplot(mtcars,aes(mpg,cyl)) + geom_path() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c4 <- ggplot(mtcars,aes(mpg,cyl)) + geom_violin() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
#arrange and add axis
grid.arrange(
arrangeGrob(c1,c2,ncol = 1, left = "Left Axis",bottom = "Bottom Left"),
arrangeGrob(c3,c4,ncol = 1, left = "Middle Axis"),
ncol = 2
)
I want to keep the Bottom Left axis label and align the the axis as well. The 'bottom' label will be slightly below the plot area.

Edit
c1 <- ggplot(mtcars,aes(mpg,cyl)) + geom_point() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c2 <- ggplot(mtcars,aes(mpg,cyl)) + geom_line() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c3 <- ggplot(mtcars,aes(mpg,cyl)) + geom_path() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c4 <- ggplot(mtcars,aes(mpg,cyl)) + geom_violin() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
#arrange and add axis
grid.arrange(
arrangeGrob(c1,c2,ncol = 1, left = "Left Axis",bottom = "Bottom Left"),
arrangeGrob(c3,c4,ncol = 1, left = "Middle Axis", bottom = " "),
ncol = 2
)
Or
library(ggplot2)
library(gridExtra)
c1 <- ggplot(mtcars,aes(mpg,cyl)) + geom_point() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c2 <- ggplot(mtcars,aes(mpg,cyl)) + geom_line() + theme(axis.title.y = element_blank()) + labs(x = "Bottom")
c3 <- ggplot(mtcars,aes(mpg,cyl)) + geom_path() + theme(axis.title.x = element_blank(),axis.title.y = element_blank())
c4 <- ggplot(mtcars,aes(mpg,cyl)) + geom_violin() + theme(axis.title.y = element_blank()) + labs(x = " ")
library(ggpubr)
ggarrange(c1, c3, c2, c4)
Created on 2021-04-06 by the reprex package (v2.0.0)

Related

Legend label combined plots (ggplot and patchwork)

I am new to R and trying to find a simple way to change the labels of the legend for combined boxplots created with ggplot and patchwork.
I am comparing the proportions of 5 different types of cells in 2 groups (controls and asthmatic). I created boxplot for each cell type, and combined them with patchwork.
plot_mac <- ggplot(asthma_desc, aes(x=control_case, y=BAL_mac_LP, color=control_case)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
then I do the same for 4 different types of cells.
patchwork <- plot_mac + plot_lym + plot_neu + plot_mast + plot_eos + plot_layout(guides = 'collect')
patchwork & theme_minimal() & scale_color_manual(values=c("black", "red")) &
theme(axis.title.x = element_blank(), axis.ticks.x=element_blank(), axis.text.x=element_blank(), text=element_text(size=7)) &
ylim(0,100)
I get the following plot
I would like to change the legend "control_case" to "Group", "1" to "control, "2" to "case". I could not make it work with labs(), scale_x_discrete() nor with theme().
Another option is to add a new column to your dataframe named Group.
Here is an example with mock mtcars dataset:
library(tidyverse)
library(ggpubr)
library(patchwork)
mtcars1 <- mtcars %>%
mutate(Group = case_when( am==0 ~"control",
am==1~"case",
TRUE ~ NA_character_))
p1 <- ggplot(mtcars1, aes(x=Group, y=mpg, color=Group)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
p2 <- ggplot(mtcars1, aes(x=Group, y=wt, color=Group)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
p3 <- ggplot(mtcars1, aes(x=Group, y=hp, color=Group)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
patchwork <- p1 + p2 + p3 + plot_layout(guides = 'collect')
patchwork & theme_minimal() & scale_color_manual(values=c("black", "red")) &
theme(axis.title.x = element_blank(), axis.ticks.x=element_blank(), axis.text.x=element_blank(), text=element_text(size=7)) &
ylim(0,100)

use if else within ggplot chunk to change colour palette

I'd like to be able to change the colour palette in ggplot2 boxplots, according to another variable data_origin.
This makes my boxplots, complete with legend:
library(hrbrthemes)
library(ggplot2)
library(reshape2)
library(tidyverse)
data_origin <- "airborne"
mytitle <- "something more than this"
legend_title <- "some words"
melted <- reshape2::melt(iris)
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
scale_fill_brewer(palette = "Greens") +
theme(
legend.position = "bottom",
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
bp1
This however drops the legend completely and ignores the if else:
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
scale_fill_brewer(legend_title, if (data_origin == "airborne" ) {palette = "Blues"} else {palette = "Greens"}) +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
bp1
Besides what #stefan suggested, there are two ways in which you can do this (that I know of). The first is using ifelse() (I moved the relevant part to the end):
data_origin <- "airborne"
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free") +
scale_fill_brewer(legend_title, palette = ifelse(
data_origin == "airborne",
"Blues",
"Greens"
))
bp1
The other one is to build the plot up in two steps:
data_origin <- "not airborne"
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
if (data_origin == "airborne") {
bp2 <- bp1 +
scale_fill_brewer(legend_title, palette = "Blues")
} else {
bp2 <- bp1 +
scale_fill_brewer(legend_title, palette = "Greens")
}
bp2
Created on 2021-08-01 by the reprex package (v2.0.0)

Removing y label from ggplot

I would like to combine 3 ggplot histograms. To do so, I am using gridExtra package. Because all plots are in one row I want to remove y titles and scales from 2 plots counting from right.
I wrote same code as always but it didn't work. Do you guys know what might be a problem? My code:
plot1 <- ggplot(testing, aes(x=residualtotal))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 1 [MW]")+
theme(panel.background=element_rect(fill = "white") )+
theme_minimal()
plot2 <- ggplot(testing, aes(x=residualtotal1))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 2 [MW]")+
theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.ticks.y = element_blank(), panel.background=element_rect(fill = "white") )+
theme_minimal()
plot3 <- ggplot(testing, aes(x=residualtotal2))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 3 [MW]")+
theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.ticks.y = element_blank(), panel.background=element_rect(fill = "white") )+
theme_minimal()
grid.arrange(plot1, plot2, plot3, ncol = 3, nrow=1)
Sample of my dataset.
Load residualtotal1 prognosis2 residualtotal2 residualtotal
89 20524 -347.6772 20888.75 -364.7539 -287.82698
99 13780 -133.8496 13889.52 -109.5207 -6.60009
100 13598 -155.9950 13728.77 -130.7729 -27.18835
103 13984 -348.4080 14310.12 -326.1226 -213.68816
129 14237 -3141.5591 17375.82 -3138.8188 -3077.32236
130 14883 -3142.0134 18026.02 -3143.0183 -3090.52193
An alternate approach:
library(tidyverse)
res_trans <- c(`residualtotal`="Residuals Model 1 [MW]",
`residualtotal1`="Residuals Model 2 [MW]",
`residualtotal2`="Residuals Model 3 [MW]")
select(testing, starts_with("resid")) %>%
gather(which_resid, value) %>%
mutate(label=res_trans[which_resid]) %>%
ggplot(aes(x=value, group=label)) +
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2))) +
facet_wrap(~label, ncol=3) +
labs(x=NULL, y=NULL) +
theme_minimal() +
theme(panel.background=element_rect(fill = "white"))
I think what you are looking for is + ylab(NULL) and to move theme() to after theme_minimal(). I've also added a widths specification to grid.arrange, since the width of the leftmost figure needs to be wider to give space to the y title.
Your code would then be
plot1 <- ggplot(testing, aes(x=residualtotal))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 1 [MW]")+
theme_minimal()
plot2 <- ggplot(testing, aes(x=residualtotal1))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 2 [MW]")+
ylab(NULL) +
theme_minimal() +
theme(axis.text.y = element_blank())
plot3 <- ggplot(testing, aes(x=residualtotal2))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 3 [MW]")+
ylab(NULL) +
theme_minimal() +
theme(axis.text.y = element_blank())
grid.arrange(plot1, plot2, plot3, ncol = 3, nrow=1, widths = c(1.35, 1, 1))

add a common border for combined ggplots

I would like to add a common border for the combined pie charts. When I use panel_border() the left and bottom lines appear as more darker than upper and right lines. I couldn't figure out my mistake.1) How can I add a common border for combined plots?
2) How can I reduce the thickness of left and bottom lines?
df1 <- data.frame(
variable = c("china","korea","canada","UK","USA"),
value = c(1632,1320,4491,991,620)
)
df2 <- data.frame(
variable = c("china","korea","canada","UK","USA"),
value = c(7376,1770,5210,5005,3947)
)
library(ggplot2)
p1 <-ggplot(df1,aes(x="", y = value, fill = variable))+ geom_bar(stat="identity", width=1) + ggtitle("Rainfall - 2014")+ panel_border() +coord_polar(theta = "y")+xlab("")+ylab("")+theme(legend.position="right", legend.title=element_blank(), plot.title = element_text(lineheight=3, face="bold", color="black", size=14))
p2 <-ggplot(df2,aes(x="", y = value, fill = variable))+ geom_bar(stat="identity", width=1) + ggtitle("Rainfall - 2015")+panel_border() +coord_polar(theta = "y")+xlab("")+ylab("")+theme(legend.position="right", legend.title=element_blank(), plot.title = element_text(lineheight=3, face="bold", color="black", size=14))
library(cowplot)
plot_grid(p1, p2, labels=c("A", "B" ))
Sanu,
The first component of the problem is that you are not seeing a border your are seeing the axis.line, and axis.text theme attributes. You need to remove these from the theme by applying element_blank() to both...
library(ggplot2)
library(cowplot)
df1 <- data.frame(
variable = c("china","korea","canada","UK","USA"),
value = c(1632,1320,4491,991,620)
)
df2 <- data.frame(
variable = c("china","korea","canada","UK","USA"),
value = c(7376,1770,5210,5005,3947)
)
p1 <-ggplot(df1, aes(x="", y = value, fill = variable))
p1 <- p1 + geom_bar(stat="identity", width=1)
p1 <- p1 + ggtitle("Rainfall - 2014")
# p1 <- p1 + panel_border()
p1 <- p1 + coord_polar(theta = "y")
p1 <- p1 + xlab("")
p1 <- p1 + ylab("")
p1 <- p1 + theme(legend.position="right",
legend.title=element_blank(),
axis.line=element_blank(),
axis.ticks=element_blank(), # the axis ticks
plot.title = element_text(lineheight=3, face="bold", color="black", size=14))
p2 <-ggplot(df2,aes(x="", y = value, fill = variable))
p2 <- p2 + geom_bar(stat="identity", width=1)
p2 <- p2 + ggtitle("Rainfall - 2015")
# p2 <- p2 + panel_border()
p2 <- p2 + coord_polar(theta = "y")
p2 <- p2 + xlab("")
p2 <- p2 + ylab("")
p2 <- p2 + theme( legend.position="right",
legend.title = element_blank(),
axis.line=element_blank(),
axis.ticks=element_blank(), # the axis ticks
plot.title = element_text(lineheight=3, face="bold", color="black", size=14))
plot_grid(p1, p2, labels=c("A", "B" ))
result:
a better solution might be to clean up the plot as follows:
library(gridExtra)
get_legend<-function(myggplot){
tmp <- ggplot_gtable(ggplot_build(myggplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- get_legend(p1)
p1 <- p1 + theme(legend.position="none")
p2 <- p2 + theme(legend.position="none")
# Arrange ggplot2 graphs with a specific width
grid.arrange(p1, p2, legend, ncol=3, widths=c(2.3, 2.3, 0.8))
result:
and now we add the border by adding...
# next line adds border
grid.rect(.5,.5,width=unit(.99,"npc"), height=unit(0.99,"npc"),
gp=gpar(lwd=3, fill=NA, col="black"))
thus:
to remove the axis test we add axis.text.x=element_blank() to the theme definition... Thus:
library(ggplot2)
library(cowplot)
df1 <- data.frame(
variable = c("china","korea","canada","UK","USA"),
value = c(1632,1320,4491,991,620)
)
df2 <- data.frame(
variable = c("china","korea","canada","UK","USA"),
value = c(7376,1770,5210,5005,3947)
)
p1 <-ggplot(df1, aes(x="", y = value, fill = variable))
p1 <- p1 + geom_bar(stat="identity", width=1)
p1 <- p1 + ggtitle("Rainfall - 2014")
# p1 <- p1 + panel_border()
p1 <- p1 + coord_polar(theta = "y")
p1 <- p1 + xlab("")
p1 <- p1 + ylab("")
p1 <- p1 + theme(legend.position="right",
legend.title=element_blank(),
axis.line=element_blank(),
axis.ticks=element_blank(), # the axis ticks
axis.text.x=element_blank(),
plot.title = element_text(lineheight=3, face="bold", color="black", size=14))
p1
p2 <-ggplot(df2,aes(x="", y = value, fill = variable))
p2 <- p2 + geom_bar(stat="identity", width=1)
p2 <- p2 + ggtitle("Rainfall - 2015")
# p2 <- p2 + panel_border()
p2 <- p2 + coord_polar(theta = "y")
p2 <- p2 + xlab("")
p2 <- p2 + ylab("")
p2 <- p2 + theme( legend.position="right",
legend.title = element_blank(),
axis.line=element_blank(),
axis.ticks=element_blank(), # the axis ticks
axis.text.x=element_blank(),
plot.title = element_text(lineheight=3, face="bold", color="black", size=14))
plot_grid(p1, p2, labels=c("A", "B" ))
library(gridExtra)
get_legend<-function(myggplot){
tmp <- ggplot_gtable(ggplot_build(myggplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- get_legend(p1)
p1 <- p1 + theme(legend.position="none")
p2 <- p2 + theme(legend.position="none")
# 4. Arrange ggplot2 graphs with a specific width
grid.arrange(p1, p2, legend, ncol=3, widths=c(2.3, 2.3, 0.8))
# next line adds border
grid.rect(.5,.5,width=unit(.99,"npc"), height=unit(0.99,"npc"),
gp=gpar(lwd=3, fill=NA, col="black"))
result:

How do I customize the margin and label settings with plot_grid?

I would like to have the title not be chopped off and have the axis labels removed from this chart that I generated with plot_grid from cowplot.
Here is my code
data(mtcars)
library(ggplot2)
library(cowplot)
mpg = ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(cyl)),data=mtcars) +
coord_flip()
am=ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(am)),data=mtcars) +
coord_flip()
vs=ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(vs)),data=mtcars) +
coord_flip()
gear = ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(gear)),data=mtcars) +
coord_flip()
p=plot_grid(mpg,am,vs,gear, labels = "Variables effecting Mileage", label_size = 14, hjust = -0.5,
+ vjust = 0.5)+theme_grey()
p
Also, if it would be simpler to create this without cowplot, what do you suggest?
Here is a cowplot only answer. It might be more what you want.
library(ggplot2)
library(cowplot)
library(gtable)
data(mtcars)
mpg = ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(cyl)),data=mtcars) +
coord_flip() + labs(x="",y="")
am=ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(am)),data=mtcars) +
coord_flip()+ labs(x="",y="")
vs=ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(vs)),data=mtcars) +
coord_flip()+ labs(x="",y="")
gear = ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(gear)),data=mtcars) +
coord_flip()+ labs(x="",y="")
p=plot_grid(mpg,am,vs,gear) +
theme_grey() +
# Use annotation text as it is centered at the x,y point
annotate("text",x=0.5,y=1.04,size=7,label="Variables affecting Mileage") +
# Add some space around the edges
theme(plot.margin = unit(c(1,0.5,0.5,0.5), "cm"))
# Suppress tick marks
p=p+scale_y_continuous(breaks=NULL)+scale_x_continuous(breaks=NULL)
# Have to turn off clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
# need to draw it with the new clip settings
grid.draw(gt)
Yields:
would this workout for you?
library(ggplot2)
library(gridExtra)
a <- ggplot() + geom_boxplot(aes(y = mpg,x = as.factor(cyl)),data=mtcars) + coord_flip() + theme_grey() + theme(axis.title.x = element_blank())
b <- ggplot() + geom_boxplot(aes(y = mpg,x = as.factor(am)),data=mtcars) + coord_flip() + theme_grey() + theme(axis.title.x = element_blank())
c <- ggplot() + geom_boxplot(aes(y = mpg,x = as.factor(vs)),data=mtcars) +
coord_flip() + theme_grey() + theme(axis.title.x = element_blank())
d <- ggplot() + geom_boxplot(aes(y = mpg,x = as.factor(gear)),data=mtcars) +
coord_flip() + theme_grey() + theme(axis.title.x = element_blank())
grid.arrange(a, b, c, d, ncol=2, top = "Variables effecting Mileage")
Thanks Mike. This does the job.
data(mtcars)
library(ggplot2)
library(cowplot)
library(gtable)
mpg = ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(cyl)),data=mtcars) +
coord_flip() + labs(x="",y="")
am=ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(am)),data=mtcars) +
coord_flip()+ labs(x="",y="")
vs=ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(vs)),data=mtcars) +
coord_flip()+ labs(x="",y="")
gear = ggplot() +
geom_boxplot(aes(y = mpg,x = as.factor(gear)),data=mtcars) +
coord_flip()+ labs(x="",y="")
p=plot_grid(mpg,am,vs,gear,
labels = "Variables effecting Mileage",
label_size = 14, hjust = -1.3[![enter image description here][1]][1], vjust = -0.1)+
theme_grey() +
# Add some space around the edges
theme(plot.margin = unit(c(1,0.5,0.5,0.5), "cm"))
# Suppress tick marks
p=p+scale_y_continuous(breaks=NULL)+scale_x_continuous(breaks=NULL)
# Have to turn off clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
# need to draw it with the new clip settings
grid.draw(gt)
Here is my plot

Resources