R语言系列4:图形初阶

R语言系列4:图形初阶


此文内容为《R语言实战》的笔记,人民邮电出版社出版。

从高中电脑课学VB开始,大一课内开始学习C++,到后来大二为了数模学习Matlab,到大三为了搞深度学习自学Python,到研究生之初学习Stata——选择一门语言对我来说就像是小时候玩冒险岛,到10级的时候是转战士好还是弓箭手好一般的纠结。我查阅了很多B乎的文章,最后觉得可能R比较合适现在的我。

作为从Python转进来R的新手,我把可能会用经常需要用到或经常需要查阅的代码贴上来,主要是为了日后方便查找,就像“字典”一样。推文的顺序与教材不同,为了简洁,我还会删除一些我个人认为不太重要的章节。我还会按照自己的学习进度发布文章,请读者见谅。

本文章仅供学习参考,请勿转载,侵删!


目录

  • 3 图形初阶
    • 3.1 使用图形
    • 3.2 一个简单的例子
    • 3.3 图形参数
      • 3.3.1 符号和线条
      • 3.3.2 颜色
      • 3.3.3 文本属性
      • 3.3.4 图形尺寸与边界尺寸
    • 3.4 添加文本、自定义坐标轴和图例
      • 3.4.1 标题
      • 3.4.2 坐标轴
      • 3.4.3 参考线
      • 3.4.4 图例
      • 3.4.5 文本标注
      • 3.4.6 数学标注
    • 3.4 图形的组合

第3章 图形初阶(非ggplot2)

3.1 使用图形

R是一个经验的图形构建平台。在通常的交互式绘画中,你可以逐条输入语句构建图形,逐渐完善图形的特征,直至想要的结果。考虑下面的代码:

attach(mtcars)
plot(wt, mpg)
abline(lm(mpg ~ wt))
title("Regression of MPG on Weight")
detach(mtcars)

图中的散点、拟合线、标题是逐个逐个被添加入图中的。


3.2 一个简单的例子

构建一个数据集:

dose <- c(20,30,40,45,60)
drugA <- c(16,20,27,40,60)
drugB <- c(15,18,25,31,40)
data <- data.frame(dose, drugA, drugB)
data
##   dose drugA drugB
## 1   20    16    15
## 2   30    20    18
## 3   40    27    25
## 4   45    40    31
## 5   60    60    40

用下面的代码可以创建一幅描述药物A的剂量和响应的关系图:

plot(data$dose, data$drugA, type="b")

这个命令把dose作为x轴,drugA作为y轴,并使用样式"b",更多的选项请见help(plot)


3.3 图形参数

我们可以通过修改称为图形参数的选项来自定义一幅图形的多个特征(字体、颜色、坐标轴、标签)。一方法是通过par()来指定这些选项。这种方式设定的参数值除非被再次修改,否则在会话结束前将一直有效。其调用格式为par(optionname=value, optionname=name,...)。请参考:

opar <- par(no.readonly = TRUE)
par(lty=2, pch=17)
plot(data$dose, data$drugA, type="b")
par(opar)

其中,我们使用lty改变了了线条的样式;使用pch改变了点的形状。请参考help(par)。你可以随心所欲地多次使用par()函数,即par(lty=2, pch=17)也可以写成:

par(lty=2)
pch(pch=17)

你也可以直接在plot中为每一幅图形单独修改一个样式,例如:

plot(data$dose, data$drugA, type="b", lty=2, pch=8)

下面介绍可以设定的许多重要的图形参数。

3.3.1 符号和线条

你可以使用图形参数指定符号和线条,如下所示:

== 参数 ==        == 描述 ==
pch               绘图符号
cex               符号大小
lty               线形
lwd               线宽

对于pch=参数,你可以使用如下的值:

plot(0, 5, pch=0, xlim=c(-1,6), ylim=c(0,6), xlab="", ylab="", xaxt="n", yaxt="n")
text(0, 5, "0", pos=2)
index =1
for (i in 5:1){
  for (j in 1:5){
    points(j, i, pch=index)
    text(j, i, as.character(index), pos=2)
    index <- index + 1
  }
}

text(2.7, 5.7, "pch=", cex=1.3)

对于lty=参数,你可以使用如下的值:

plot(c(1,5), c(1,1), type="b", 
     lty=1, pch=20, 
     xlim=c(0,6), ylim=c(0,7), 
     xlab="", ylab="", 
     xaxt="n", yaxt="n")
text(1, 1, "1", pos=2)
for (i in 2:6){
  lines(c(1,5), c(i,i), type="b", lty=i, pch=20)
  text(1, i, as.character(i), pos=2)
}

text(2.85, 6.7, "lty=", cex=1.3)

上面两个图的代码不必细究,看完后面的就懂了。

3.3.2 颜色

R中有若干和颜色相关的参数,例如:

== 参数 ==        == 描述 ==
col               默认的绘图颜色
col.axis          坐标轴刻度文字的颜色
col.lab           坐标轴名称的颜色
col.main          标题颜色
col.sub           副标题的颜色
fg                图形的前景色
bg                图形的背景色

在R中,可以通过颜色下标、颜色名称、16进制颜色值、RGB值或HSV值指定颜色。比如:

col=1
col="white"
col="#FFFFFF"
col=rgb(1,1,1)
col=hsv(0,0,1)

都表示白色。函数colors()可以返回可用颜色的名称:

colors()

3.3.3 文本属性

图形参数同样可以用来指定字号、字体和字样。下标阐释了用于控制本文大小的参数:

== 参数 ==        == 描述 ==
cex               相对于默认大小的放大缩小倍数
cex.axis          坐标轴刻度文字的缩放倍数
cex.lab           坐标轴标签的缩放倍数
cex.main          标题的缩放倍数
cex.sub           副标题的缩放倍数
font              1=常规,2=粗体,3=斜体,4=斜粗体,5=符号字体
font.axis         坐标轴刻度的文字样式
font.lab          坐标轴标签的样式
font.main         标题的字体样式
font.sub          副标题的字体样式
ps                字体磅值
family            使用的字体族

距离来说,如果执行语句

par(font.lab=3, cex.lab=1.5, font.main=4, cex.main=2)

那么之后创建的图形都拥有斜体、1.5倍于默认大小的坐标轴标签,以及粗体、2倍于默认大小的标题。

我们还可以简单的设置字体。比如,在windows中,运行:

windowsFonts(
  A = windowsFont("Arial Black")
  B = windowsFont("Bookman Old Style")
)

那么在后面需要用到字体的时候,就可以直接使用family=A来调用字体,例如:

par(family=A)

如果是macOS系统,那么请用quartzFonts()

3.3.4 图形尺寸与边界尺寸

以下参数可以控制图形尺寸和边界尺寸:

== 参数 ==        == 描述 ==
pin               以英寸表示的图形尺寸(宽和高)
mai               以数值向量表示边界大小(顺序为下、左、上、右),单位为英寸
mar               同上,单位为英分。默认值为 c(5,4,4,2)+.1

比如,代码:

par(pin=c(4,3), mai=c(1, .5, 1, .2))

可以生成一幅4英寸宽、3英寸高、上下边界为1英寸、坐边界为.5英寸、由边界为.2英寸的图形。

让我们对这一节所学的知识强化之前的简单图例:

opar <- par(no.readonly = TRUE)
par(pin=c(2, 3))
par(lwd=1, cex=.75)
par(cex.axis=.75, font.axis=3)
plot(data$dose, data$drugA, type="b", pch=19, lty=2, col="red")

3.4 添加文本、自定义坐标轴和图例

除了图形参数,许多高级绘图函数(如plot, hist, boxplot)也允许自行定义坐标轴和文本选项。比如以下代码在图形上添加来标题(main)、副标题(sub)、坐标轴标签(xlab、ylab)并制定了坐标轴范围(xlim、ylim):

plot(data$dose, data$drugA, type="b",
     col='blue', lty=2, pch=2, lwd=1,
     main="Clinical Trials for Drug A",
     sub="This is a hypothetical data",
     xlab="Dosage", ylab="Drug Response",
     xlim=c(0, 60), ylim=c(0, 70))

再次提醒,并非所有函数都支持这些选项。另外,从更精细的控制和模块化的角度考虑,你可以使用本节余下部分描述的函数来控制标题、坐标轴、图例和文本标注的外观。

某些高级绘图函数会自动帮你添加默认的标题和标签,你可以在plot()par()中使用ann=FALSE来移除它们

3.4.1 标题

可以使用title()函数为图形添加标题和坐标轴标签,其格式为:

title(main = "main title",
      sub = "subtitle",
      xlab = "x-axis label",
      ylab = "y-axis label")

函数title()中也可以指定其他图形参数(如文本大小、字体、旋转角度和颜色)。比如:

title(main = "main title",
      sub = "subtitle",
      xlab = "x-axis label",
      ylab = "y-axis label",
      col.lab="green", cex.lab=.75)

请使用help查看更多细节。

3.4.2 坐标轴

你可以使用函数axis()来创建自定义的坐标轴,而非使用R中的默认坐标轴,其格式为:

axis(side, at=, labels=, pos=, las=, tck=, ...)

常用的参数用:

== 参数 ==        == 描述 ==
side              表示图形的哪边绘制坐标轴(1=下、2=左、3=上、4=右)
at                数值型向量,表示需要绘制刻度线的位置
labels            字符型向量,表示置于刻度线旁边的问题标签(如果缺省,就是at中的)
pos               坐标轴线绘制位置的坐标
lty               线条类型
col               线条和刻度线的颜色
las               标签是否平行于(=0)或垂直于(=2)坐标轴
tck               刻度线的长度
(...)             其他参数

自定义创建坐标轴时,你应该禁用高级绘图函数自动生成的坐标轴。参数axes=FALSE将禁用全部坐标轴。参数xaxt="n"yaxt="n"将分别禁用x、y坐标轴(但会留下框线,只是删除了刻度)

3.4.3 参考线

函数abline()可以用于为图添加参考线,格式为:

abline(h=yvalues, v=xvalues)

此函数的参数也可以用于指定其他图形参数,例如:

abline(v=seq(1, 10, 2), lty=2, col="blue")

表示在1、3、5、7、9的位置添加了垂直的蓝色虚线

3.4.4 图例

可以使用legend()来添加图例,其格式为:

legend(location, title, legend, ...)

更多细节请参考help(legend)。下面给出一个画图的成品的代码:

dose <- c(20,30,40,45,60)
drugA <- c(16,20,27,40,60)
drugB <- c(15,18,25,31,40)

opar <- par(no.readonly = TRUE)

par(lwd=2, cex=.75, font.lab=2)

plot(dose, drugA, type="b",
     pch=15, lty=1, col="red",
     ylim=c(0, 60),
     main="Drug A vs. Drug B",
     xlab="Drug Dosage", ylab="Drug Response")
lines(dose, drugB, type="b",
      pch=17, lty=2, col="blue")

abline(h=c(30), lwd=1.5, lty=2, col="gray")

legend("topleft", inset=.05, title="Drug Type", c("A", "B"),
       lty=c(1,2), pch=c(15,17), col=c("red", "blue"))

3.4.5 文本标注

可以通过函数text()mtext()将文本添加到图形上。text()可以向绘图区域内部添加文本,而mtext()则向图形的四个边界之一添加文本,其格式为:

text(location, "texts", pos, ...)
mtext("texts", side, line=n, ...)

常见选项为:

== 选项 ==       == 描述 ==
location        c(x,y),也可以用locater(1)使用鼠标点击
pos             文本相对于点的位置,1=下、2=左、3=上、4=右
                  * 同时可以指定参数offset=偏移量
side            用来放置文本的边,1=下、2=左、3=上、4=右
                  * 可以指定line=来内移或外移文本
                  * 也可以使用sdj=0将文本左下对其或adj=1右上对齐

比如:

attach(mtcars)
plot(wt, mpg,
     main="Mileage vs. Car Weight",
     xlab="Weight", ylab="Mileage",
     pch=18, col="blue")
text(wt, mpg,
     row.names(mtcars),
     cex=.6, pos=4, col="red")

又比如:

opar <- par(no.readonly = TRUE)
par(cex=1.5)
plot(1:7, 1:7, type="n", xaxt="n", yaxt="n", xlab="", ylab="")
text(3, 3, "Example of defalut text")
text(2, 2, family="STSong", "华文宋体")
text(4, 4, family="mono", "Example of moni-spaced text")
text(5, 5, family="serif", "Example of serif text")
text(4, 6, family="TimesNewRomanPSMT", "Example of Times New Roman text")

3.4.6 数学标注

请参考help(plotmath)获得更多细节。


3.5 图形的组合

在R中使用函数par()layout()可以很容易第组合多个图形为一幅图。这两个函数的使用场景并不相同,下面会分别讲解。

你可以使用par()函数的mfrow=c(nrows, ncols)来创建按行填充的图形矩阵,例如:

attach(mtcars)
par(mfrow=c(2,2))
plot(wt, mpg, main="Scatterplot of wt vs. mpg")
plot(wt, disp, main="Scatterplot of wt vs. disp")
hist(wt, main="Historam of wt")
boxplot(wt, main="Boxplot of wt")

你也可以使用layout(mat)方法,其中mat是一个矩阵,它指定了所要组合的多个图形的所在位置:

attach(mtcars)
layout(matrix(c(1,2,3,3), nrow = 2))
plot(wt, mpg, main="Scatterplot of wt vs. mpg")
plot(wt, disp, main="Scatterplot of wt vs. disp")
hist(wt, main="Historam of wt")

layout()还可以指定图形的高度和宽度,见:

attach(mtcars)
layout(matrix(c(1,1,2,3), nrow = 2, byrow = TRUE), 
       widths=c(3, 1), heights=c(1, 2))
hist(wt)
hist(mpg)
hist(disp)

上面的代码指定了,第一行的高度:第二行的高度=1:2。左图的宽度:右图的宽度=3:1。

可见,layout()可以很方便地摆放图的位置及其相对大小。所以如果只是图形的简单排列,我个人更倾向于使用layout(mat)方法。

如果需要对图形布局进行精确控制,那么可以使用par()更加方便,你可以使用其fit=参数完成这个任务。例如:

par(fig=c(0, .8, 0, .8))
plot(mtcars$wt, mtcars$mpg,
     xlab="Miles Per Gallon",
     ylab="Car Weight")

par(fig=c(0, .8, .4, 1), new=TRUE)
boxplot(mtcars$wt, horizontal = TRUE, axes=FALSE)


par(fig=c(.6, 1, 0, .8), new=TRUE)
boxplot(mtcars$mpg, axes=FALSE)

mtext("Enhanced Scatterplot", side=3, outer=TRUE, line=-3)

fig=c(0, .8, 0, .8)的意思是,下面这张图,将占据整个图形的x的0-80%,y的0-80%的部分。置于两个boxplot的占据位置,需要反复尝试才能寻找到合适的(这是因为boxplot()会产生一个图框,我们把图框消掉以后它在图中的具体位置是不知道的)。你可以使用axes=TRUE进行实验理解它。

你可能感兴趣的:(R语言系列4:图形初阶)