R語言學習2:繪圖
阿新 • • 發佈:2021-02-16
本系列是一個新的系列,在此係列中,我將和大家共同學習R語言。由於我對R語言的瞭解也甚少,所以本系列更多以一個學習者的視角來完成。
參考教材:《R語言實戰》第二版(Robert I.Kabacoff),書中所提到的[John Cook的優秀博文](https://www.johndcook.com/blog/r_language_for_programmers/),關於程式碼規範的《[來自Google的R語言編碼風格指南](https://nanx.me/rstyle/)》。
[Toc]
## Part 1:圖形引數
### Unit 1:點型和線型
`plot()`是R中為物件作圖的一個泛型函式,它的輸出由所繪製物件的型別不同而不同。如果`x`和`y`是兩個等長的數字向量,則以下程式碼將繪製點集$(x,y)$,並用線段將其連線。
```R
plot(x, y, type="b")
```
這裡`type="b"`代表同時繪製點和線。還有以下的幾種`type`屬性的選擇:
- `"p"`:只繪製點,不繪製線段。
- `"l"`:只繪製線段,不繪製點。
- `"b"`:繪製點和線,但實線不通過點。
- `"o"`:繪製點和線,且實線會通過點,與`"b"`的視覺效果不同。
- `"h"`:只繪製各點到$x$軸的豎線,不繪製點和線。
- `"s"`:繪製階梯型曲線。
- `"S"`:繪製階梯型區間,但是階梯方向不同。
- `"n"`:不繪製任何點、線。
在使用`plot()`作圖**之前**,可以使用`par()`函式修改圖形的引數,這個函式可以任意次呼叫。在使用`par()`修改圖形引數之前,往往會加入以下兩句:
```R
opar <- par(no.readonly=TRUE)
...
par(opar)
```
當呼叫`par(opar)`後,將還原**預設引數環境**。
以下是用於指定符號和線條型別的引數:
- `pch`:指定繪製點時使用的符號,範圍是$\{0,1,\cdots,25\}$。
- `cex`:指定符號的大小,表示繪圖符號相對於預設大小的縮放倍數,預設值是1。
- `lty`:指定線條型別,範圍是$\{1,2,\cdots,6\}$。
- `lwd`:指定線條寬度,表示之於預設值的相對粗細,預設值是1。
也可以直接在`plot`處加上這四個引數:
```R
plot(x, y, type="b", pch=11, lty=2, cex=2, lwd=2)
```
### Unit 2:顏色
以下是用於指定顏色的引數:
- `col`:預設的繪圖顏色,可以傳入一個向量並迴圈使用。
- `col.axis`:座標軸刻度文字的顏色。
- `col.lab`:座標軸標籤文字的顏色。
- `col.main`:標題顏色。
- `col.sub`:副標題顏色。
- `fg`:圖形前景色,如座標軸線。
- `bg`:圖形背景色。
顏色的指定,可以用顏色下標、顏色名字、十六進位制顏色值、RGB值、HSV值來指定,函式`colors()`可以返回所有可用顏色的名稱(657種)。
可以用`rainbow(n)`建立一個$n$種連續的彩虹形顏色列表,可以用`gray(vector)`來獲得一個灰度色列表,常用的`vector=0:n/n`,是一個$[0,1]$之間的均勻列表。
`RColorBrewer`是一個用於建立顏色的常用包,其中`brewer.pal(n, name)`可以從調色盤`name`中建立一個顏色值的向量,以下程式段是一個`brewer.par()`函式的使用示例。
```R
library(RColorBrewer)
n <- 9
mycolor <- brewer.pal(n, "Set1") # 使用的顏色集合是"Set1"
barplot(rep(1,n), col = mycolor)
```
可以使用`display.brewer.all()`顯示所有調色盤的顏色,或者`display.brewer.pal(name)`顯示某個調色盤的顏色。`brewer.pal.info`命令可以給出所有調色盤的列表。
### Unit 3:文字
字型族和字樣通過以下引數進行控制。
- `cex`:相對預設大小的縮放倍數,預設值是1(代表以下一類,**不要直接呼叫**)。
- `cex.axis`:座標軸刻度文字的縮放倍數。
- `cex.lab`:座標軸標籤的縮放倍數。
- `cex.main`:標題的縮放倍數。
- `cex.sub`:副標題的縮放倍數。
- `font`:整數,指定字型樣式。$\{1,2,3,4,5\}$分別代表常規、粗體、斜體、粗斜體、符號字型(代表以下一類,不要直接呼叫)。
- `font.axis`:座標軸刻度文字的字型樣式。
- `font.lab`:座標軸標籤的字型樣式。
- `font.main`:標題的字型樣式。
- `font.sub`:副標題的字型樣式。
- `ps`:字型磅值,文字的最終大小為`ps*cex`。
- `family`:繪製文字時使用的字型族,標準取值為`serif`(襯線)、`sans`(無襯線)、`mono`(等寬)。
字型族的設定稍顯複雜,**在Windows系統中**,`mono`對映為TT Courier New,`sarif`對映為TT Times New Roman,`sans`對映為TT Arial,這裡TT指True Type。如果想要使用其他字型,需要建立新的對映,使用`windowsFonts()`和`windowsFont()`來建立。
```R
x <- c(20, 30, 40, 45, 60)
y <- c(16, 20, 27, 40, 60)
windowsFonts(
A=windowsFont("Arial Black"),
B=windowsFont("Bookman Old Style"),
C=windowsFont("Comic Sans MS")
)
par(pch=17, lty=6, cex=2, lwd=3) # 注意cex引數也會對文字產生影響
par(col='red')
par(font.main=4, family="C", ps=6)
plot(x, y, type="b", main="A Simple Try")
```
### Unit 4:圖形尺寸與邊界尺寸
控制圖形尺寸和邊界大小的引數為:
- `pin`:以英寸表示的圖形尺寸,是一個二元列表(寬和高)。
- `mai`:以數值向量表示的邊界大小,單位為英寸(下、左、上、右)。
- `mar`:以數值向量表示的邊界大小,單位為英分(下、左、上、右)。
## Part 2:新增要素
### Unit 1:新增標題和座標軸標籤
新增標題和座標軸標籤:使用`title()`函式,其呼叫格式為
```R
title(main="main title",
sub="subtitle",
xlab="x-axis label",
ylab="y-axis label")
```
可以在`title()`函式中新增其他圖形引數,如`col.main`、`col.lab`、`cex.lab`等。
### Unit 2:添加個性化座標軸
如果要添加個性化的座標軸,通常要在`plot()`函式中設定一些圖形引數:
- `ann`:取`FALSE`時,將不會畫出標題,包括主標題和副標題。
- `bty`:設定邊框樣式,預設為`"o"`表示全部畫出,還有`"l"`(左下)、`"7"`(右上)、`"c"`(上下左)、`"u"`(左下右)、`"]"`(上下右)、`"n"`(無)。
- `xaxs`和`yaxs`:設定$x, y$軸的範圍,預設為`"r"`表示比範圍略大,`"i"`表示和給定作圖範圍完全相同。
- `xaxt`和`yaxt`:可以取`"n"`,此時座標軸、刻度線和刻度值將不會畫出。
- `axes`:如果取`FALSE`,則所有座標軸和框線都不會被畫出。
新增自定義的座標軸:使用`axis()`函式,其呼叫格式為
```R
axis(side, at=, labels=, pos=, lty=, col=, las=, tck=, ...)
```
各個引數的釋義為
- `side`:$\{1,2,3,4\}$,表示在圖形的哪一邊繪製座標軸(下、左、上、右)。
- `at`:數值型向量,表示需要繪製刻度線的位置。
- `labels`:字元型向量,刻度線旁的文字標籤,如果預設則直接使用`at`中的值。
- `pos`:座標軸線繪製位置的座標。
- `lty`:線條型別。
- `col`:線條和刻度線顏色。
- `las`:標籤平行於座標軸`=0`,垂直於座標軸`=2`。
- `tck`:刻度線的長度,以相對於繪圖區域大小的分數表示,預設為-0.01,負值表示在圖形外側。
```R
x <- c(20, 30, 40, 45, 60)
y <- c(16, 20, 27, 40, 60)
windowsFonts(
A=windowsFont("Arial Black"),
B=windowsFont("Bookman Old Style"),
C=windowsFont("Comic Sans MS")
)
par(pch=17, lty=6, cex=1, lwd=3)
par(col='red')
par(font.main=2, family="C", ps=12)
plot(x, y, type="b", main="A Simple Try", yaxt="n")
z <- c(20, 21, 22, 23, 24, 26, 28, 30, 35, 42, 50, 60)
axis(4, at=z, labels=z, col.axis='blue', pos=50, las=2, lty=2, tck=-0.02, )
```
### Unit 3:新增圖例和參考線
要新增參考線,應當使用`abline()`函式,其使用格式為
```R
abline(h=yvalues, v=xvalues)
```
這裡`h`代表新增水平參考線的高度位置,`v`代表新增垂直參考線的水平位置。可以在其中新增其他圖形引數。
要新增圖例,應當使用`legend()`函式,其使用格式為
```R
legend(location, title, legend, ...)
```
- `location`:指定圖例的位置,可以給定圖例左上角的$x,y$座標,也可以使用`locator(1)`用滑鼠點選,還可以使用`bottom, bottomleft, left, topleft, top, topright, right, bottomright, center`等關鍵字。
- `title`:圖例標題的字串。
- `legend`:圖例標籤組成的字元型向量。
以下給出書上的案例:
```R
rm(list=ls())
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 = T)
par(lwd=2, cex=1.5, 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=30, lwd=1.5, lty=2, col="gray")
library(Hmisc)
minor.tick(nx=3, ny=3, tick.ratio=0.5) # 新增次要刻度線
legend("topleft", inset=0.05, title="Drug Type", c("A", "B"),
lty=c(1, 2), pch=c(15, 17), col=c("red", "blue"))
par(opar)
```
### Unit 4:新增輔助文字
文字新增可以通過函式函式`text()`,向圖形內部(通常是各個點)新增文字,使用格式為
```R
text(location, "text to place", pos, ...)
```
- `location`:文字的位置引數,可以是一對$(x, y)$座標,也可以通過`location=locator(1)`用滑鼠來確定擺放位置。
- `pos`:文字相對於位置引數的方位,$\{1,2,3,4\}$代表下、左、上、右。還可以追加指定引數`offset`作為偏移量。
還可以通過`mtext()`向圖形的四個邊界之一新增文字,使用格式為
```R
mtext("text to place", side, line=n, ...)
```
- `side`:指定擺放文字的邊,$\{1,2,3,4\}$代表下、左、上、右。
- `line`:內移或外移文字,值越大,文字外移的程度越大。
- `adj`:文字可以向左下對齊`=0`,或向右上對齊`=1`。
## Part 3:圖形組合
規則排布:可以使用`par()`函式中的圖形引數`mfrow=c(nrows, ncols)`來建立按行填充的、行數為`nrows`、列數為`ncols`的圖形矩陣。以下案例書上的例項程式碼,資料集為R語言內建的`mtcars`。
```R
rm(list=ls())
opar <- par(no.readonly = T)
par(mfrow=c(2, 2)) # 將繪圖區域分成四塊
attach(mtcars)
plot(wt, mpg, main="Scatterplot of wt vs. mpg") # 第一個圖
plot(wt, disp, main="Scatterplot of wt vs. disp") # 第二個圖
hist(wt, main="Histogram of wt") # 第三個圖
boxplot(wt, main="Boxplot of wt") # 第四個圖
detach(mtcars)
par(opar)
```
複雜排布:可以使用`layout(matrix)`函式來組合圖形,這裡`matrix`給定了圖形的所在位置,如
$$
\begin{pmatrix}
1 & 1 \\
2 & 3
\end{pmatrix}
$$
就代表第一幅圖位於第一行的1、2列,第二幅圖位於第二行第一列,第三幅圖位於第二行第二列。
```R
rm(list=ls())
opar <- par(no.readonly = T)
attach(mtcars)
mat <- matrix(c(1, 1, 2, 3), nrow=2, ncol=2, byrow=T)
layout(mat) # 按照mat矩陣給出劃分
hist(wt, main = "Graph_1")
hist(mpg, main = "Graph_2")
hist(disp, main = "Graph_3")
detach(mtcars)
par(opar)
```
為了精細控制每幅圖形的相對大小,可以在`layout()`函式中使用`widths`和`heights`兩個引數,它們分別是各列寬度值構成的向量與各行寬度值構成的向量。現在,在上述程式碼中加入這兩個引數。
```R
rm(list=ls())
opar <- par(no.readonly = T)
attach(mtcars)
mat <- matrix(c(1, 1, 2, 3), nrow=2, ncol=2, byrow=T)
layout(mat, widths = c(3, 1), heights = c(1, 1.5)) # 按照mat矩陣給出劃分
hist(wt, main = "Graph_1")
hist(mpg, main = "Graph_2")
hist(disp, main = "Graph_3")
detach(mtcars)
par(opar)
```
精細控制:可以使用`par()`函式的引數`fig`來精細控制,它接受四個$[0,1]$之間的數,分別代表圖形在視窗內所佔有矩形的四個端點。一般還要加入`new=TRUE`,使得新加入的圖形與原圖形位於同樣的畫布中。
注意,如果遇到`Error in plot.new(): figure margins too large`,則應當**修改引數**,這是因為由於裝置的原因,子圖所需的大小與設定的引數衝