使用圖形
在本章中,我們將討論處理圖形的一般方法。我們首先探討如何創建和保存圖形,然后關注如何修改那些存在于所有圖形中的特征,包括圖形的標題、坐標軸、標簽、顏色、線條、符號和文本標注。我們的焦點是那些可以應用于所有圖形的通用方法。(在后續各章,我們將關注特定類型的圖形。)最后,我們將研究組合多幅圖形為單幅圖形的各種方法。
R是一個驚艷的圖形構建平臺。這里我特意使用了“構建”一詞。在通常的交互式會話中,你可以通過逐條輸入語句構建圖形,逐漸完善圖形特征,直至得到想要的效果。
考慮以下五行代碼:
attach(mtcars)
plot(wt, mpg)
abline(lm(mpg~wt))
title("Regression of MPG on Weight")
detach(mtcars)
首句綁定了數據框 mtcars 。第二條語句打開了一個圖形窗口并生成了一幅散點圖,橫軸表示車身重量,縱軸為每加侖汽油行駛的英里數。第三句向圖形添加了一條最優擬合曲線。第四句添加了標題。最后一句為數據框解除了綁定。在R中,圖形通常都是以這種交互式的風格繪制的(參見圖3-1)。
可以通過代碼或圖形用戶界面來保存圖形。要通過代碼保存圖形,將繪圖語句夾在開啟目標圖形設備的語句和關閉目標圖形設備的語句之間即可。例如,以下代碼會將圖形保存到當前工作目錄中名為 mygraph.pdf 的PDF文中:
pdf("myfirstpdf.pdf")
attach(mtcars)
plot(wt,mpg)
abline(lm(mpg~wt))
title("Regression of ...")
dev.off()
除了 pdf() ,還可以使用函數 win.metafile() 、 png() 、 jpeg() 、 bmp() 、 tiff() 、 xfig()和 postscript() 將圖形保存為其他格式。(注意,Windows圖元文件格式僅在Windows系統中可用。)關于保存圖形輸出到文件的更多細節,可以參考1.3.4節。
通過圖形用戶界面保存圖形的方法因系統而異。對于Windows,在圖形窗口中選擇“文件”→“另存為”,然后在彈出的對話框中選擇想要的格式和保存位置即可。在Mac上,當Quartz圖形窗口處于高亮狀態時,點選菜單欄中的“文件”→“另存為”即可。其提供的輸出格式僅有PDF。在UNIX系統中,圖形必須使用代碼來保存。在附錄A中,我們將考慮每個系統中可用的備選圖形用戶界面,這將給予你更多選擇。
通過執行如 plot() 、 hist() (繪制直方圖)或 boxplot() 這樣的高級繪圖命令來創建一幅新圖形時,通常會覆蓋掉先前的圖形。如何才能創建多個圖形并隨時查看每一個呢?
dev.new()
一個簡單的例子
讓我們從表3-1中給出的假想數據集開始。它描述了病人對兩種藥物五個劑量水平上的響應
情況。
使用以下代碼可以創建一幅描述藥物A的劑量和響應關系的圖形:
pdf("pdf1.pdf")
dose = c(20,30,40,45,60)
drugA= c(16,20,27,40,60)
drugB= c(15,18,25,31,40)
plot(dose,drugA,type = "b")
dev.off()
plot() 是R中為對象作圖的一個泛型函數(它的輸出將根據所繪制對象類型的不同而變化)。本例中, plot(x, y, type="b") 將 x 置于橫軸,將 y 置于縱軸,繪制點集(x, y),然后使用線段將其連接。選項 type="b" 表示同時繪制點和線。使用 help(plot) 可以查看其他選項。結果如圖3-2所示。
圖形參數
我們可以通過修改稱為圖形參數的選項來自定義一幅圖形的多個特征(字體、顏色、坐標軸、標題)。
修改圖形參數的一種方法是通過函數 par() 來指定這些選項。以這種方式設定的參數值除非被再次修改,否則將在會話結束前一直有效。其調用格式為 par(optionname=value,optionname=name,…) 。不加參數地執行 par() 將生成一個含有當前圖形參數設置的列表。添加參數 no.readonly=TRUE 可以生成一個可以修改的當前圖形參數列表。
繼續我們的例子,假設你想使用實心三角而不是空心圓圈作為點的符號,并且想用虛線代替實線連接這些點。你可以使用以下代碼完成修改:
opar <- par(no.readonly=TURE)# 先備份當前參數
par(lty=2, pch=17)
plot(dose ,drugA, type="b")
par(opar)# 恢復當前參數,使得par不對其他作圖產生影響
結果如圖3-3所示。
首個語句復制了一份當前的圖形參數設置。第二句將默認的線條類型修改為虛線( lty=2 )并將默認的點符號改為了實心三角( pch=17 )。然后我們繪制了圖形并還原了原始設置。線條類型和符號將在3.3.1節中詳述。
指定圖形參數的第二種方法是為高級繪圖函數直接提供 optionname=value 的鍵值對。這種
情況下,指定的選項僅對這幅圖形本身有效。你可以通過代碼:
plot(dose ,drugA, type="b",lty=2, pch=17)
來生成與上圖相同的圖形。
符號和線條
如你所見,可以使用圖形參數來指定繪圖時使用的符號和線條類型。相關參數如表3-2所示。
選項 pch= 用于指定繪制點時使用的符號。可能的值如圖3-4所示。
對于符號21~25,你還可以指定邊界顏色( col= )和填充色( bg= )。
選項 lty= 用于指定想要的線條類型。可用的值如圖3-5所示。
顏色
R中有若干和顏色相關的參數。表3-3列出了一些常用參數。
函數 colors() 可以返回所有可用顏色的名稱。參見R Color Chart。R中也有多種用于創建連續型顏色向量的函數,包括 rainbow() 、 heat.colors() 、 terrain.colors() 、 topo.colors()以及 cm.colors() 。舉例來說, rainbow(10) 可以生成10種連續的“彩虹型”顏色。多階灰度色可使用 gray() 函數生成。這時要通過一個元素值為0和1之間的向量來指定各顏色的灰度。gray(0:10/10) 將生成10階灰度色。
mycolors1=rainbow(10)
mycolors2=gray(0:10/10)
pdf("piechart1.pdf")
pie(rep(1,10),labels = mycolors1,col=mycolors1)
pie(rep(1,10),labels = mycolors2,col=mycolors2)
dev.off()
[圖片上傳失敗...(image-84d70c-1577187273408)]
文本屬性
圖形參數同樣可以用來指定字號、字體和字樣。表3-4闡釋了用于控制文本大小的參數。字體族和字樣可以通過字體選項進行控制(見表3-5)。
讓我們使用最近學到的選項來強化之前的簡單圖形示例。
pdf("test1.pdf")
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(pin = c(2, 3))
par(lwd = 2, cex = 1.5)
par(cex.axis = .75,font.axis = 3)
plot(dose, drugA, type = "b", pch = 19, lty = 2, col = "red")
plot(dose, drugB, type = "b", pch = 23, lty = 6, col = "blue", bg = "green")
par(opar)
dev.off()
圖形尺寸與邊界尺寸
最后,可以使用表3-6列出的參數來控制圖形尺寸和邊界大小。
添加文本、自定義坐標軸和圖例
除了圖形參數,許多高級繪圖函數(例如 plot 、 hist 、 boxplot )也允許自行設定坐標軸和文本標注選項。舉例來說,以下代碼在圖形上添加了標題( main )、副標題( sub )、坐標軸標簽( xlab 、 ylab )并指定了坐標軸范圍( xlim 、 ylim )。結果如圖3-8所示。
pdf("test2.pdf")
dose <- c(20, 30, 40, 45, 60)
drugA <- c(16, 20, 27, 40, 60)
drugB <- c(15, 18, 25, 31, 40)
plot(dose, drugA, type = "b", col = "red",
lty = 2, pch = 2, lwd = 2,
main = "Clinical Trials for Drug A",
sub = "This is hypothetical data",
xlab = "Doseage", ylab = "Drug Response",
xlim = c(0, 60), ylim = c(0, 70))
dev.off()
藥物A劑量和響應的折線圖。添加了標題、副標題和自定義的坐標軸:
再次提醒,并非所有函數都支持這些選項。請參考相應函數的幫助以了解其可以接受哪些選項。從更精細的控制和模塊化的角度考慮,你可以使用本節余下部分描述的函數來控制標題、坐標軸、圖例和文本標注的外觀。
標題
可以使用 title() 函數為圖形添加標題和坐標軸標簽。調用格式為:
title(main = "My Title", col.main = "red",
sub = "My Sub-title", col.sub = "blue",
xlab = "My X label", ylab = "My Y label",
col.lab = "green", cex.lab = 0.75)
坐標軸
你可以使用函數 axis() 來創建自定義的坐標軸,而非使用R中的默認坐標軸。其格式為:
axis(side, at =, labels =, pos=, lty=, col=, las=, tck=, ...)
各參數已詳述于表3-7中。
創建自定義坐標軸時,你應當禁用高級繪圖函數自動生成的坐標軸。參數 axes=FALSE 將禁用全部坐標軸(包括坐標軸框架線,除非你添加了參數 frame.plot=TRUE )。參數 xaxt="n" 和yaxt="n" 將分別禁用X軸或Y軸(會留下框架線,只是去除了刻度)。代碼清單3-2中是一個稍顯笨拙和夸張的例子,它演示了我們到目前為止討論過的各種圖形特征。結果如圖3-9所示。
# 生成數據
pdf("pdf.pdf")
x <- c(1: 10)
y <- x
z <- 10/x
opar <- par(no.readonly = TRUE)
# 修改邊界大小
par(mar = c(5, 4, 4, 8) + 0.1)
# 繪制x對y的圖形
plot(x, y, type = "b", pch = 21, col = "red", yaxt = "n", lty = 3, ann = FALSE)
# 添加x對1/x的直線
lines(x, z, type = "b", pch = 22, col = "blue", lty = 2)
# 繪制自定義坐標軸
axis(2, at = x, labels = x, col.axis = "red", las = 2)
axis(4, at = z, labels =round(z, digits = 2), col.axis = "blue", las = 2, cex.axis = 0.7, tck = -0.01)
# 添加文本
mtext("y = 10/x", side = 4, line = 3, cex.lab = 1, las = 2, col = "blue")
# 添加標題
title("An Example of Creative Axes", xlab = "X values", ylab = "Y = X")
par(opar)
dev.off()
各種坐標軸選項的演示:
到目前為止,我們已經討論過代碼清單3-2中除 lines() 和 mtext() 以外的所有函數。使用plot() 語句可以新建一幅圖形。而使用 lines() 語句,你可以為一幅現有圖形添加新的圖形元素。在3.4.4節中,你會再次用到它,在同一幅圖中繪制藥物A和藥物B的響應情況。函數 mtext()用于在圖形的邊界添加文本。我們將在3.4.5節中講到函數 mtext() ,同時會在第11章中更充分地討論 lines() 函數。
次要刻度線
注意,我們最近創建的圖形都只擁有主刻度線,卻沒有次要刻度線。要創建次要刻度線,你需要使用 Hmisc 包中的 minor.tick() 函數。如果你尚未安裝 Hmisc 包,請先安裝它(參考1.4.2節)。你可以使用代碼:
library(Hmisc)
minor.tick(nx=n, ny=n, tick.ration=n)
來添加次要刻度線。其中 nx 和 ny 分別指定了X軸和Y軸每兩條主刻度線之間通過次要刻度線劃分得到的區間個數。 tick.ratio 表示次要刻度線相對于主刻度線的大小比例。當前的主刻度線長度可以使用 par("tck") 獲取。舉例來說,下列語句將在X軸的每兩條主刻度線之間添加1條次要添加標題和文本刻度線,并在Y軸的每兩條主刻度線之間添加2條次要刻度線:
library(Hmisc)
minor.tick(nx=2, ny=3, tick.ration=0.5)
次要刻度線的長度將是主刻度線的一半:
(然而并不是預想的那樣,有點奇怪╥﹏╥)
參考線
函數 abline() 可以用來為圖形添加參考線。
abline(h=yvalues, v=xvalues)
函數 abline() 中也可以指定其他圖形參數(如線條類型、顏色和寬度)。舉例來說:
abline(h=c(1,5,7), col="blue")
在y為1、5、7的位置添加了水平實線。
圖例
當圖形中包含的數據不止一組時,圖例可以幫助你辨別出每個條形、扇形區域或折線各代表哪一類數據。我們可以使用函數 legend() 來添加圖例(果然不出所料)。其使用格式為:
lengend(location, title, legend, ...)
常用選項詳述于表3-8中。
其他常用的圖例選項包括用于指定盒子樣式的 bty 、指定背景色的 bg 、指定大小的 cex ,以及指定文本顏色的 text.col 。指定 horiz=TRUE 將會水平放置圖例,而不是垂直放置。關于圖例的更多細節,請參考 help(legend) 。這份幫助中給出的示例都特別有用。
讓我們看看對藥物數據作圖的一個例子(代碼清單3-3)。你將再次使用我們目前為止講到的許多圖形功能。結果如圖3-10所示。
# 創建數據
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 = 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 = c(30), lwd = 1.5, lty = 2, col = "gray")
#繪制次要刻度線
library(Hmisc)
minor.tick(nx = 3, ny = 3, tick.ratio = 0.5)
# 添加圖例
legend ("topleft", inset = .05, title = "Drug Type",
legend = c("A", "B"), lty = c(1, 2),
pch = c(15, 17), col = c("red", "blue"))
par(opar)
圖3-10的幾乎所有外觀元素都可以使用本章中討論過的選項進行修改。除此之外,還有很多其他方式可以指定想要的選項。最后一種需要研究的圖形標注是向圖形本身添加文本,請繼續讀下一節。
文本標注
我們可以通過函數 text() 和 mtext() 將文本添加到圖形上。 text() 可向繪圖區域內部添加文本,而 mtext() 則向圖形的四個邊界之一添加文本。使用格式分別為:
text(location, "text to place", pos, ...)
mtext("text to place", side, line=n, ...)
常用選項列于表3-9中。
除了用來添加文本標注以外, text() 函數也通常用來標示圖形中的點。我們只需指定一系列的x, y坐標作為位置參數,同時以向量的形式指定要放置的文本。x、y和文本標簽向量的長度應當相同。下面給出了一個示例,結果如圖3-11所示。
這里,我們針對數據框 mtcars 提供的32種車型的車重和每加侖汽油行駛英里數繪制了散點圖。
函數 text() 被用來在各個數據點右側添加車輛型號。各點的標簽大小被縮小了40%,顏色為紅色。
作為第二個示例,以下是一段展示不同字體族的代碼:
opar <- par(no.readonly = TRUE)
par(cex = 1.5)
plot(1:7, 1:7, type = "n")
text(3, 3, "Example of default text")
text(4, 4, family = "mono", "Example of mono-spaced text")
text(5, 5, family = "serif", "Example of serif text")
par(opar)
在Windows系統中輸出的結果如圖3-12所示。這里為了獲得更好的顯示效果,我們使用 par()函數增大了字號。
數學標注
最后,你可以使用類似于TeX中的寫法為圖形添加數學符號和公式。請參閱 help(plotmath)以獲得更多細節和示例。要即時看效果,可以嘗試執行 demo(plotmath) 。部分運行結果如圖3-13所示。函數 plotmath() 可以為圖形主體或邊界上的標題、坐標軸名稱或文本標注添加數學符號。
同時比較多幅圖形,我們通常可以更好地洞察數據的性質。所以,作為本章的結尾,下面討論將多幅圖形組合為一幅圖形的方法。
圖形的組合
在R中使用函數 par() 或 layout() 可以容易地組合多幅圖形為一幅總括圖形。此時請不要擔心所要組合圖形的具體類型,這里我們只關注組合它們的一般方法。后續各章將討論每類圖形的繪制和解讀問題。
你可以在 par() 函數中使用圖形參數 mfrow=c(nrows, ncols) 來創建按行填充的、行數為nrows 、列數為 ncols 的圖形矩陣。另外,可以使用 nfcol=c(nrows, ncols) 按列填充矩陣。
舉例來說,以下代碼創建了四幅圖形并將其排布在兩行兩列中:
attach(mtcars)
opar <- par(no.readonly=TRUE)
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="Histogram of wt")
boxplot(wt, main="Boxplot of wt")
par(opar)
detach(mtcars)
作為第二個示例,讓我們依3行1列排布3幅圖形。代碼如下:
attach(mtcars)
opar <- par(no.readonly=TRUE)
par(mfrow=c(3,1))
hist(wt)
hist(mpg)
hist(disp)
par(opar)
detach(mtcars)
所得圖形如圖3-15所示。請注意,高級繪圖函數 hist() 包含了一個默認的標題(使用 main=""可以禁用它,抑或使用 ann=FALSE 來禁用所有標題和標簽)。
函數 layout() 的調用形式為 layout(mat) ,其中的 mat 是一個矩陣,它指定了所要組合的多個圖形的所在位置。
在以下代碼中,我們再次將一幅圖形置于第1行,兩幅圖形置于第2行。但第1行中圖形的高度是第2行中圖形高度的三分之一。除此之外,右下角圖形的寬度是左下角圖形寬度的四分之一:
要理解這幅圖的繪制原理,請試想完整的繪圖區域:左下角坐標為(0,0),而右上角坐標為(1,1)。圖3-19是一幅示意圖。參數 fig= 的取值是一個形如 c(x1, x2, y1, y2) 的數值向量。
圖3-19 使用圖形參數 fig= 指定位置第一個 fig= 將散點圖設定為占據橫向范圍0-0.8,縱向范圍0-0.8。上方的箱線圖橫向占據0-0.8,縱向0.55-1。右側的箱線圖橫向占據0.65-1,縱向0-0.8。 fig= 默認會新建一幅圖形,所以在添加一幅圖到一幅現有圖形上時,請設定參數 new=TRUE 。
我將參數選擇為0.55而不是0.8,這樣上方的圖形就不會和散點圖拉得太遠。類似地,我選擇了參數0.65以拉近右側箱線圖和散點圖的距離。你需要不斷嘗試找到合適的位置參數。