R语言坐标轴的操作: 双坐标轴/截断坐标轴
本文会详细介绍绘图过程中如何进行条形图的绘制并通过修改参数对图像进行调整,本文旨在通过绘图实例讲解各个参数的使用方法,希望大家能够活学活用。
特别要注意的是,本文内容中涉及的具体参数数值是根据绘图数据和生成图像的大小设置的,在自己绘制图像时需要根据自己的数据进行调整,切勿直接套用。
例图展示
原本文章中的图像如下所示,途中通过两个相邻的条形展示了不同样品中抗生素抗性基因和可移动基因单元的丰度,并且由于抗生素抗性基因可以根据对应的抗生素进行分类,因而使用堆叠的色块展示不同类型抗生素抗性基因的丰度。
我在绘图的过程中,对上述图像进行了改进,以堆叠的色块展示不同样品中不同类型抗生素抗性基因的检出数目,以“点+垂线”的方式表示可移动基因单元的检出数目,并分别应用两个纵坐标轴进行标识,同时在图像中增加了一些用于表示分组的文本,最终的图像就是下方这样。
先给出绘图的完整代码:
args.mges.number <- read.table("ARGs_MGEs_number.txt",header = TRUE,sep = "\t",row.names = 1)
args.mges.number <- as.matrix(args.mges.number)
library(RColorBrewer)
tiff(filename = "ARGs.MGEs.number.tiff",width = 12000,height = 9000,res = 600,compression = "lzw")
par(mar=c(6.3,5,4,10))
bar <- barplot(args.mges.number[1:8,],names.arg = c(rep("",13)),col = brewer.pal(8,"Set3"),border = "black",xlim = c(0,15),axes = F,ylim = c(0,40))
axis(side = 2,at = seq(0,40,5),las = 2,line = -1.55,cex.axis = 2.2,lwd = 3,lwd.ticks = 3,font = 2)
par(xpd = TRUE)
par(new = T)
par(mar = c(4,5,4,10))
plot(x = bar,y = args.mges.number[9,],type = "p",col = "black",axes = F,xlim = c(0,15),xlab = "",ylab = "",ylim = c(0,7),pch = 19,bg = "black",cex = 4)
par(xpd = TRUE)
par(new = T)
par(mar = c(4,5,4,10))
plot(x = bar,y = args.mges.number[9,],type = "h",col = "black",axes = F,xlim = c(0,15),xlab = "",ylab = "",ylim = c(0,7),bty = "o",lwd =5)
axis(side = 1, at = bar,line = -1,labels = FALSE,cex.axis = 2.2,lwd = 3,lwd.ticks = 3,font = 2)
text(x = bar, y = -0.24,adj = c(1,0.8),labels = colnames(args.mges.number),cex = 2.4, font = 2,srt = 45)
axis(side = 4,at = c(0:7),line = 4,las = 2,cex.axis = 3,lwd = 3,lwd.ticks = 3,font = 2)
mtext("The detected number of ARGs in all samples",side = 2,line = 3,font = 2,cex = 3)
mtext("The detected number of MGEs in all samples",side = 4,line = 9,font = 2,cex = 3)
par(xpd=TRUE)
par(new = T)
plot(0:1, 0:1, type="n", xlab="",ylab="", axes=FALSE)
legend(0,1.12,legend = rownames(args.mges.number[1:8,]),fill = brewer.pal(9,"Set3"),bty = "n",ncol = 4,text.width = 0.2,cex = 2.5,text.font = 2)
legend(0.01,1.033,legend = "MGEs",pch = 19,col = "black",bty = "n",cex = 2.5,pt.cex = 3.3,text.font = 2,text.width = 0.2,x.intersp = 1.35)
segments(0.095,0.72,0.315,0.72,col = "black",lwd = 5)
segments(0.335,0.6,0.555,0.6,col = "black",lwd = 5)
segments(0.575,0.47,0.795,0.47,col = "black",lwd = 5)
segments(0.815,0.43,1.035,0.43,col = "black",lwd = 5)
text(x = 0.205,y = 0.74,labels = "Group A",font = 2,cex = 2.5)
text(x = 0.445,y = 0.62,labels = "Group B",font = 2,cex = 2.5)
text(x = 0.685,y = 0.49,labels = "Group C",font = 2,cex = 2.5)
text(x = 0.925,y = 0.45,labels = "Group D",font = 2,cex = 2.5)
arrows(x0 = 0.1525,y0 = 0.85,x1 = 0.09,y1 = 0.85,lwd = 4,col = "black")
text(x = 0.21,y = 0.85,labels = "Control",font = 2,cex = 2.5)
dev.off()
绘图所需的数据就是普通的数据框形式。
barplot
该图像使用barplot()函数进行条形图的绘制,首先介绍一下barplot()函数的基本信息。
barplot(height, width = 1, space = NULL,
names.arg = NULL, legend.text = NULL,
beside = FALSE, horiz = FALSE, density = NULL,
angle = 45, col = NULL, border = par("fg"),
main = NULL, sub = NULL, xlab = NULL, ylab = NULL,
xlim = NULL, ylim = NULL, xpd = TRUE, log = "",
axes = TRUE, axisnames = TRUE,
cex.axis = par("cex.axis"), cex.names = par("cex.axis"),
inside = TRUE, plot = TRUE, axis.lty = 0, offset = 0,
add = FALSE, args.legend = NULL, ...)
各参数意义:
height为进行绘图的数据;
width定义bar的宽度;
space定义不同bar之间的间隔;
names.arg定义每一个bar下方的名称,如果为NULL则默认为数据中的列名;
legend.text定义legend中的名称,默认为数据中的行名;
beside定义绘图方式,FALSE为堆叠图,TRUE为并列图;
horiz定义绘图方式,FALSE为纵向绘图,TRUE为横向绘图;
density为底纹的密度;
angle为底纹的倾斜角度;
col为定义条形填充颜色;
border定义条形边框颜色,NA为去除边框;
main和sub定义标题和副标题;
xlab和ylab定义x和y轴的名称;
xlim和ylim定义x和y轴的界限;
xpd定义是否允许bar超过图像的范围;
log定义数据是否需要log转换;
axes定义是否需要显示垂直的或水平的轴;
axisnames是否显示轴的名字;
cex.axis和cex.names定义轴标签和bar表现的大小;
inside当space为0时,相邻bar之间是否用线间隔;
plot是否绘图;
axis.lty定义轴的线型;
add定义bar是否是添加进一个已有的图像中;
args.legend应用list函数通过legend命令的参数调整图例。
绘图过程详解
首先载入绘图数据和绘图所需要的包。
#导入绘图数据,将第一行和第一列设置为行名和列明
args.mges.number <- read.table("ARGs_MGEs_number.txt",header = TRUE,sep = "\t",row.names = 1)
#将绘图数据转换为矩阵形式
args.mges.number <- as.matrix(args.mges.number)
#载入所需要的颜色包
library(RColorBrewer)
条形图绘制
#定义图像输出路径和大小
tiff(filename = "ARGs.MGEs.number.tiff",width = 12000,
height = 9000,res = 600,compression = "lzw")
#定义绘图区边界
par(mar=c(6.3,5,4,10))
#绘制条形图
bar <- barplot(args.mges.number[1:8,],
names.arg = c(rep("",13)),
col = brewer.pal(8,"Set3"),
border = "black",xlim = c(0,15),
axes = F,ylim = c(0,40))
这里绘图边界的大小要根据实际需要进行调整,主要是要满足后续点线图与条形图的匹配,以及为坐标轴和图例留出足够的空间。
条形图只使用[1:8,]选择前8行进行绘图,第9行是可移动基因单元,用于绘制“点+垂线”图。
names.arg将x轴坐标设置为空,axes = F将坐标轴隐藏,这样才能通过后续的自主添加调整坐标轴及标签的位置,自带的坐标轴位置固定并且各项参数不好调整。
xilm和ylim设置x和y轴的范围,x轴设置为样品数目+2,y轴根据绘图数据调整,我在绘图前已经规划好将图例放在上方,因而y轴的范围进行了适当的扩大。
将条形图赋值为bar,后续会持续用到。
添加条形纵坐标
axis(side = 2,at = seq(0,40,5),
las = 2,line = -1.55,cex.axis = 2.2,
lwd = 3,lwd.ticks = 3,font = 2)
side = 2表示在左侧,at确定坐标轴间隔,las = 2表示标签与间隔线垂直,font = 2对标签进行加粗。
line调整轴与图像的间隔,cex.axis调整轴标签的大小,lwd调整轴的线宽,lwd.ticks调整轴中间隔线的长度,通过这几个参数的调整,使坐标轴的展示效果达到自己满意的要求。
“点+垂线”图的绘制
#使得新的图像可以在绘图区以外显示
par(xpd = TRUE)
#新建一个绘图区用于添加散点图
par(new = T)
#定义新绘图区的边界
par(mar = c(4,5,4,10))
#进行散点图的绘制
plot(x = bar,y = args.mges.number[9,],
type = "p",col = "black",axes = F,
xlim = c(0,15),xlab = "",ylab = "",
ylim = c(0,7),pch = 19,bg = "black",cex = 4)
首先通过par(xpd = TRUE)命令使得接下来绘制的图像可以在条形图绘图边界部分显示,防止后续图像显示不全。
接下来要新建用于绘制“点+垂线”图的绘图区。
使用plot()函数先绘制散点图,x轴坐标选择上一步绘制的条形图bar,即可自动匹配横坐标位置,纵坐标使用[]选择第9行数据绘制可移动基因单元的检出数目。
同样应用axes = F隐藏坐标轴,将x和y轴标签设置为空,选择type = “p”绘制散点图,点的形状选择19为实心圆形,颜色调控为黑色。
其它参数根据图像的展示情况调整直至满意。
之后再使用plot()函数绘制垂线图。
par(xpd = TRUE)
par(new = T)
par(mar = c(4,5,4,10))
plot(x = bar,y = args.mges.number[9,],
type = "h",col = "black",axes = F,
xlim = c(0,15),xlab = "",ylab = "",
ylim = c(0,7),bty = "o",lwd =5)
同样也要新建一个绘图区域,绘图区域的参数要与散点图一致。
注意该图像y轴的范围,要稍微大一些,使得“点”与条形最上端相对和谐,便于后续添加分组信息。
特别需要注意的是,散点图和垂线图的绘图区边界实际上是由垂线图决定的,最终要通过调整会图边界保证垂线和点位于条形的正中,并且垂线的末端与条形的最下端在同一条水平线上。
垂线图的基本参数也要与散点图保持一致,使用type = “h”绘制垂线图,lwd调整垂线的线宽。
添加其它坐标轴
首先添加横坐标信息。
axis(side = 1, at = bar,line = -1,
labels = FALSE,cex.axis = 2.2,lwd = 3,
lwd.ticks = 3,font = 2)
text(x = bar, y = -0.24,adj = c(1,0.8),
labels = colnames(args.mges.number),
cex = 2.4, font = 2,srt = 45)
side = 1规定坐标轴在下方,at = bar以坐标轴间隔与图像的位置,labels = FALSE隐藏轴的标签,line调整轴与图像的间距。
cex.axis、lwd、lwd.ticks和font的参数与之前绘制的条形图纵坐标轴保持一致。
之后使用text()函数添加x轴标签,这样做是为了能够方便地对标签进行调整,例如改变其对其方式、大小、位置、旋转角度等。
接下来添加“点+垂线”图对应的纵坐标轴。
axis(side = 4,at = c(0:7),line = 4,
las = 2,cex.axis = 3,lwd = 3,
lwd.ticks = 3,font = 2
相关参数与第一条纵坐标轴一致,除了应用side = 4将其放置在图像右侧,并且根据会图数据改变其标签间隔。
最后使用mtext()命令添加两个坐标轴对应的labels。
mtext("The detected number of ARGs in all samples",
side = 2,line = 3,font = 2,cex = 3)
mtext("The detected number of MGEs in all samples",
side = 4,line = 9,font = 2,cex = 3)
添加图例
首先要新建一个绘图区,并且建立一个空的图用来辅助图例的添加。
par(xpd=TRUE)
par(new = T)
plot(0:1, 0:1, type="n", xlab="",ylab="", axes=FALSE)
之后要分两次添加图例,第一次添加条形图的图例,第二次添加“点+垂线”图的图例。
legend(0,1.12,legend = rownames(args.mges.number[1:8,]),
fill = brewer.pal(9,"Set3"),bty = "n",ncol = 4,
text.width = 0.2,cex = 2.5,text.font = 2)
在条形图的图例添加时,要注意预留第二个图例的位置。
使用ncol调整图例的列数,text.width调整不同列见图例的宽度以达到对图例文字的完整展示。
其它参数根据出图效果进行调整。
接下来添加“点+垂线”图的图例。
legend(0.01,1.033,legend = "MGEs",pch = 19,
col = "black",bty = "n",cex = 2.5,
pt.cex = 3.3,text.font = 2,
text.width = 0.2,x.intersp = 1.35
通过xy坐标调整图例的位置,cex、pt.cex调整点和文字的大小,x.intersp调整点和文字的间距,使得该图例看起来与之前插入的条形图图例为同一个图例。
指示文字的插入
最后我们分别通过线段、箭头和文字的插入来指示分组信息。
segments(0.095,0.72,0.315,0.72,col = "black",lwd = 5)
segments(0.335,0.6,0.555,0.6,col = "black",lwd = 5)
segments(0.575,0.47,0.795,0.47,col = "black",lwd = 5)
segments(0.815,0.43,1.035,0.43,col = "black",lwd = 5)
text(x = 0.205,y = 0.74,labels = "Group A",font = 2,cex = 2.5)
text(x = 0.445,y = 0.62,labels = "Group B",font = 2,cex = 2.5)
text(x = 0.685,y = 0.49,labels = "Group C",font = 2,cex = 2.5)
text(x = 0.925,y = 0.45,labels = "Group D",font = 2,cex = 2.5)
对于包含多个样品的样品组,使用segments()在其条形上方插入线段以表示线段下方的样品属于同一组,之后使用text()函数在线段上加入分组名称。
arrows(x0 = 0.1525,y0 = 0.85,x1 = 0.09,
y1 = 0.85,lwd = 4,col = "black")
text(x = 0.21,y = 0.85,labels = "Control",
font = 2,cex = 2.5)
dev.off()
#dev.off()用于结束绘图,并按照绘图最开始的命令将图像输出
对于只有一个样本的分组,可以使用arrows()在其附近添加指示箭头,之后在箭头末端应用text()函数添加分组名称。
在处理数据时,我们经常会遇到个别数据的值与整体差别较大,导致图像绘制出来正常数据无法区分的情况,此时就需要用到坐标轴中断来实现不同尺度数据的同时展示。
在R中可以通过plotrix包实现坐标轴的中断。
散点图的坐标轴中断
通过plotrix包中的gap.plot绘制坐标轴中断的散点图,之后使用axis.break调整坐标中断的形式。
照例先介绍这两个绘图函数的详细参数。
gap.plot(x,y,gap,gap.axis="y",bgcol="white",
breakcol="black",brw=0.02,xlim=range(x),
ylim=range(y),xticlab,xtics=NA,yticlab,
ytics=NA,lty=rep(1,length(x)),
col=rep(par("col"),length(x)),
pch=rep(1,length(x)),add=FALSE,
stax=FALSE,...)
各参数意义:
x和y为绘图的数据;
gap为中断的范围;
gap.axis定义在哪个轴中断;
bgcol为背景颜色;
breakcol为中断标志颜色;
brw为中断相比于图像比例
xlim和ylim为图像的x和y轴范围;
xticlab和yticlab为x和y轴刻度的标签;
xtics和ytics为x和y轴刻度位置。
我们先来生成一组随机的绘图数据。
x <- c(1:15)
y <- c(rnorm(5,mean = 1),rnorm(5,mean = 1)+10,rnorm(5,mean = 2))
col <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3)
首先画一个正常的图。
plot(x,y,col = col,pch = 16,
xlab = "",ylab = "",main = "Plot")
接下来绘制坐标轴中断的图。
gap.plot(x,y,gap = c(4,8),
col = col,pch = 16,
xlab = "",ylab = "",main = "Gap plot")
gap.plot绘图的方法与正常的plot基本没有区别,只需要注意gap.axis和brw参数。
gap.axis确定中断的轴,默认为y轴,如果要中断x轴则设置为gap.axis = “x”。
brw规定中断区域相对于图像整体的比例,默认为0.02。
我们可以看到,坐标轴中断的默认形式时分成两个图,但是有时我们并不喜欢这种展示形式,这就需要用到另一个函数axis.break。
axis.break(axis=1,breakpos=NULL,pos=NA,
bgcol="white",breakcol="black",
style="slash",brw=0.02)
各参数意义:
axis定义中断哪个轴,1为横轴2为纵轴;
breakpos在什么地方进行中断(按照轴的单位);
pos在什么位置进行中断(按照轴的比例);
bgcol背景颜色;
breakcol中断标志的颜色
style中断的方式,gap、slash或zigzag;
brw中断相比于图形宽度的比例。
⚠️axis.break中axis、breakpos和brw要与gap.plot一致。
axis.break(2,breakpos = c(4,8),breakcol="snow",style="gap")
axis.break(2,breakpos = 4,breakcol="black",style="slash")
axis.break(4,breakpos = 4,breakcol="black",style="slash")
条形图的坐标轴中断
使用gap.barplot绘制中断的条形图,用法几乎和gap.plot一样。
gap.barplot(y,gap = c(4,8),col = col,
xlab = "",ylab = "",ylim = c(0,12),
main = "Gap barplot")
axis.break(2,breakpos = c(4,8),breakcol="snow",style="gap")
#去掉中间的那两道横线
axis.break(2,breakpos = 4,breakcol="black",style="slash")
#在左侧Y轴把gap位置换成slash
axis.break(4,breakpos = 4,breakcol="black",style="slash")
#在右侧Y轴把gap位置换成slash
如需联系EasyShu团队
https://github.com/Easy-Shu/EasyShu-WeChat
数据可视化之美系列书籍
Github
https://github.com/Easy-Shu/Beautiful-Visualization-with-python
Github
https://github.com/Easy-Shu/Beautiful-Visualization-with-R