介绍
有时候我们需要将多个图像排列好放到一张图上,对于R语言基础包的函数,比如plot, barplot, hist等,是可以通过par, layout进行排版,但是对于ggplot的图像,我们需要使用别的方法
几种方法实现
传统的par和layout的方法
par方法
方法只适用于基础包的函数(plot, barplot, hist等),不适用于ggplot。
par(mfrow = c(1,2))
plot(mtcars[,1:2],pch =19)
plot(iris[,1:2],pch = 19)
layout方法
layout(matrix(c(2,0,1,3),2,2,byrow=TRUE), widths=c(3,1), heights=c(1,3), respect=TRUE)
设置布局,布局矩阵是
2 0
1 3
表示左下是第一个画,左上是第二个,右下是第三个画,右上不画图。widths = c(3,1)表示从左到右宽度比是3比1,heights=c(1,3)表示高度从上到下是1比三, respect=True单位列宽与单位行高在设备上是相同的物理度量
示例如下
#读入数据
air<-read.csv("airpollution.csv")
#首先设置布局
layout(matrix(c(2,0,1,3),2,2,byrow=TRUE), widths=c(3,1), heights=c(1,3), TRUE)
#画散点图
par(mar=c(5.1,4.1,0.1,0))
plot(air$Respirable.Particles~air$Nitrogen.Oxides,pch=19,
col="black",xlim=c(0,600),ylim=c(0,80),xlab="Nitrogen Oxides Concentrations",ylab="Respirable Particle Concentrations")
#画X的直方图,在散点图的上方
par(mar=c(0,4.1,3,0))
hist(air$Nitrogen.Oxides,breaks=seq(0,600,100),ann=FALSE,axes=FALSE,
col="black",border="white")
#画Y的直方图,在散点图的右方
yhist <- hist(air$Respirable.Particles,breaks=seq(0,80,10),plot=FALSE)
par(mar=c(5.1,0,0.1,1))
barplot(yhist$density,horiz=TRUE,space=0,axes=FALSE,col="black",border="white")
ggplot的可以使用ggpubr包的函数ggarange
使用install.packages("ggpubr")安装ggpubr包。
ggarrange(...,
plotlist = NULL,
ncol = NULL,
nrow = NULL,
labels = NULL,
label.x = 0,
label.y = 1,
hjust = -0.5,
vjust = 1.5,
font.label = list(size = 14, color = "black", face = "bold", family = NULL),
align = c("none", "h", "v", "hv"),
widths = 1,
heights = 1,
legend = NULL,
common.legend = FALSE)
…:需要画的图对象,可以直接放放多个ggplot的对象
plotlist,也可以将ggplot对象放到列表里,给到这个plotlist参数
ncol和nrow是要排列成几行几列
labels每个图的标签,label.x label.y hjust vjust font.label都是调整labels的位置参数,
align各个图的排列方式,是纵向(v)还是横向排列(h),
widths和heights调整各图的长宽比列
legend是各图的图例,
commn.legend公共的图例
示例如下
cols <- brewer.pal(n=5, name='Set1') #配置色板
# 用plist存放ggplot对象,再用ggarrange进行排版并画图
plist <- list()
plist[[1]] <- ggplot(df1,aes(x=sample,y=count,fill=group))+theme_classic()+geom_bar(stat='identity')+
theme(legend.position = "none",
axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank()) +
ylab('HMR#')+
scale_fill_manual(values=c('darkgray',cols))
plist[[2]] <- ggplot(df3,aes(x=sample,y=count,fill=group))+theme_classic()+geom_bar(stat='identity')+
theme(axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank(),legend.position = "none")+
scale_fill_brewer(palette='Dark2')+ylab('CpG#')
plist[[3]] <- ggplot(df5,aes(x=sample,y=percent.copy.altered,fill=namecn))+theme_classic()+geom_bar(stat='identity')+
theme(axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank(),legend.position = "none")+
scale_fill_manual(values='darkgrey')+ylab('% CN Altered')
plist[[4]] <- ggplot(df5,aes(x=sample,y=mutation_count,fill=namemut))+theme_classic()+geom_bar(stat='identity')+
theme(axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank(),legend.position = "none")+
scale_fill_manual(values='darkgrey')+ylab('Mut/Mb')+scale_y_log10()
plist[[5]] <- ggplot(df6,aes(x=sample,y=count,fill=group))+theme_classic()+geom_bar(stat='identity')+
theme(axis.title.x=element_blank(),
axis.text.x=element_text(angle=90,hjust=1,vjust=0.5,colour=df6$color),
axis.ticks.x=element_blank(),
legend.position = "none")+
scale_fill_brewer(palette='Set2')+ylab('# SV')
ggarrange(plotlist=plist,
ncol=1,
nrow=length(plist),
heights=c(3,1,1,1,2) ,
align="v")
ggsave(fn_fig1a, height=8, width=14)
ggplot的也可以使用grid排版
grid包是R语言自带的底层的绘图系统,可以比较细的对图,线条,点等进行排版布局。我们这里包装成一个函数,用法跟ggarrange很像。
示例:
# Multiple plot function
#
# ggplot objects can be passed in ..., or to plotlist (as a list of ggplot
# objects)
# - cols: Number of columns in layout
# - layout: A matrix specifying the layout. If present, 'cols' is ignored.
#
# If the layout is something like matrix(c(1,2,3,3), nrow=2, byrow=TRUE),
# then plot 1 will go in the upper left, 2 will go in the upper right, and
# 3 will go all the way across the bottom.
# e=0.15, # extra height needed for last plot (vertical layout),
# or extra width for first plot (horizontal layout)
multiplot <- function(..., plotlist=NULL, file, cols=1,
layout=NULL, horizontal=FALSE, e=0.15) {
require(grid)
# Make a list from the ... arguments and plotlist
plots = c(list(...), plotlist)
numPlots = length(plots)
#message(paste0('>>>>>>>INFO: num plots 2 = ', numPlots), '\n')
# If layout is NULL, then use 'cols' to determine layout
if (is.null(layout)) {
# Make the panel
# ncol: Number of columns of plots
# nrow: Number of rows needed, calculated from # of cols
layout = matrix(seq(1, cols * ceiling(numPlots/cols)),
ncol = cols, nrow = ceiling(numPlots/cols))
}
if (numPlots==1) {
print(plots[[1]])
} else {
## set up heights/widths of plots
# extra height needed for last plot (vertical layout),
# or extra width for first plot (horizontal layout)
hei = rep(1, numPlots)
# bottom plot is taller
hei[numPlots] = hei[numPlots]*(1+e)
wid = rep(1, numPlots)
# first left plot is wider
wid[1] = wid[1]*(1+e)
# Set up the page
grid.newpage()
if(horizontal){
pushViewport(viewport(layout = grid.layout(nrow(layout),
ncol(layout), widths=wid)))
}else{
pushViewport(viewport(layout = grid.layout(nrow(layout),
ncol(layout), heights=hei)))
}
# Make each plot, in the correct location
for (i in 1:numPlots) {
# Get i,j matrix positions of the regions containing this subplot
matchidx = as.data.frame(which(layout == i, arr.ind = TRUE))
print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
layout.pos.col = matchidx$col))
}
}
}
library(ggplot2)
p1 <- ggplot(iris, aes(x = Sepal.Length)) + geom_histogram() + theme_bw()
p2 <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Width)) + geom_point() + theme_bw()
# 直接使用ggplot对象画图
multiplot(p1,p2)
# 将ggplot对象放入列表中,再用列表画图, 并设置两列的排列方式
plot_lst <- list()
plot_lst[[1]] <- p1
plot_lst[[2]] <- p2
multiplot(plotlist = plot_lst, cols = 2)
原文