ggplot2包的目的是提供一個(gè)全面的、基于語法的、連貫一致的圖形生成系統(tǒng),允許用戶創(chuàng)建新穎的、有創(chuàng)新性的數(shù)據(jù)可視化圖形。
1、簡介ggplot2語法
下面將從一個(gè)例子來看看ggplot2的基本語法。
library(ggplot2) # 載入ggplot2包
ggplot(data=mtcars, aes(x=wt,y=mpg)) + # 指定繪圖的數(shù)據(jù) (1)
geom_point(pch=17,color='red',size=2) + # 繪圖函數(shù)及其參數(shù) (2)
geom_smooth(method='lm',color='green',linetype=2) + # 繪圖函數(shù)(擬合曲線)(3)
labs(title='ggplot2', x='Weight', y='MPG') + # 添加注釋信息(標(biāo)題)(4)
theme(plot.title = element_text(hjust = 0.5)) # 調(diào)整標(biāo)題位置 (5)
現(xiàn)在我們來一步步解析上面的代碼:
(1)初始化圖形并指定要用到的數(shù)據(jù)來源(mtcars)和變量(wt、mpg)。aes()
函數(shù)指定每個(gè)變量扮演的角色,這里的wt映射到x軸數(shù)值,mpg映射到y(tǒng)軸數(shù)值。當(dāng)需要對(duì)數(shù)據(jù)進(jìn)行分類時(shí),還可將分類因子映射到圖形性狀或顏色上面;
(2)繪圖函數(shù)(也稱幾何函數(shù))使用一個(gè)或幾個(gè)函數(shù)向圖中添加幾何對(duì)象(簡寫為geom),包括點(diǎn)、線、條、箱線圖和陰影區(qū)域,這里向圖中添加了散點(diǎn)圖以及一條擬合曲線(代碼3)。當(dāng)需要在一個(gè)圖中使用多個(gè)數(shù)據(jù)來源進(jìn)行畫圖時(shí),可以單獨(dú)在每個(gè)幾何函數(shù)中指定數(shù)據(jù)源;
(4)labs()
函數(shù)是可選的,用來添加注釋(包括軸標(biāo)簽和標(biāo)題信息);
(5)theme()
函數(shù)用來設(shè)置全局配置,這里設(shè)置了標(biāo)題的位置為中間;
除了上面的一些基本設(shè)置外,ggplot2還提供了分組和小面化(faceting)以及圖形組合的方法,這些較為高級(jí)的方法將在下面進(jìn)行介紹。
2、幾何函數(shù)
ggplot()
函數(shù)可用來指定要繪制的數(shù)據(jù)源和變量,也可不在ggplot()中設(shè)置而在每個(gè)幾何函數(shù)中單獨(dú)設(shè)置所用的數(shù)據(jù)源及變量,幾何函數(shù)則指定了這些變量如何在視覺上進(jìn)行展示(點(diǎn)、線、條、箱線圖等)。使用命令ls(pattern = '^geom_', env = as.environment('package:ggplot2'))
可以查看所有可用的幾何函數(shù),常用的幾何函數(shù)如下表:
函數(shù) | 圖形 | 常用選項(xiàng) |
---|---|---|
geom_bar() | 條形圖 | color、fill、alpha |
geom_boxplot() | 箱線圖 | color、fill、alpha、notch、width |
geom_density() | 密度圖 | color、fill、alpha、linetype |
geom_hist0gram() | 直方圖 | color、fill、alpha、linetype、binwidth |
geom_hline() | 水平線 | color、alpha、linetype、size |
geom_jitter() | 抖動(dòng)圖 | color、size、alpha、shape |
geom_line() | 線圖 | colorvalpha、linetype、size |
geom_point() | 散點(diǎn)圖 | color、alpha、shape、size |
geom_rug() | 地毯圖(軸須圖) | color、size |
geom_smooth() | 擬合曲線 | method、formula、color、fill、linetype、size |
geom_text() | 文字注解 | 很多,參加函數(shù)幫助 |
geom_violin() | 小提琴圖 | color、fill、alpha、linetype |
geom_vline() | 垂線 | color、alpha、linetype、size |
對(duì)于幾何函數(shù)中每個(gè)選項(xiàng)的意義,詳見下表:
選項(xiàng) | 詳述 |
---|---|
color | 對(duì)點(diǎn)、線和填充區(qū)域的邊界進(jìn)行著色 |
fill | 對(duì)填充區(qū)域著色,如條形和密度區(qū)域 |
alpha | 顏色的透明度,從0(完全透明)到1(不透明) |
linetype | 線條類型,1=實(shí)線,2=虛線,3=點(diǎn),4=破折號(hào),5=長破折號(hào),6=雙破折號(hào) |
size | 點(diǎn)的尺寸和線的寬度 |
shape | 點(diǎn)的性狀(和pch一樣,0=方形,1=圓形,2=三角形,等等) |
position | 繪制諸如條形圖和點(diǎn)等對(duì)象的位置。對(duì)于條形圖來說,‘dodge’將分組條形圖并排,‘stacked’則為堆疊條形圖,‘fill’標(biāo)準(zhǔn)化堆疊條形圖。對(duì)于點(diǎn)來說,‘jitter’抖動(dòng)減少點(diǎn)重疊 |
binwidth | 直方圖的寬度 |
notch | 表示方塊圖是否為缺口(TRUE、FALSE),常見于箱線圖 |
sides | 地毯圖的安置('b'=底部,'l'=左部,'t'=頂部,'r'=右部,'bl'=左下部,等等) |
width | 箱線圖的寬度 |
library(ggplot2)
mtcars$am <- factor(mtcars$am, levels=c(0,1), labels=c('Automatic', 'Manual'))
ggplot() +
geom_point(data=mtcars, aes(x=wt,y=mpg,shape=am, color=am),size=2) + # 性狀和顏色都使用am進(jìn)行分組
geom_smooth(data=mtcars, aes(x=wt,y=mpg),method='lm',color='green',linetype=2) +
labs(title='ggplot2', x='Weight', y='MPG') +
theme(plot.title = element_text(hjust = 0.5))
下圖是對(duì)例子的一個(gè)改進(jìn),在上面的代碼中可以看到,我們將數(shù)據(jù)分別放在了各個(gè)幾何函數(shù)中,之所以這么做是為了對(duì)所有的數(shù)據(jù)進(jìn)行擬合曲線,若將數(shù)據(jù)源一起放在ggplot()
中進(jìn)行設(shè)置的話,后面進(jìn)行數(shù)據(jù)擬合的話會(huì)分別對(duì)am的分組數(shù)據(jù)進(jìn)行擬合。
下面再看一個(gè)箱線圖的簡單例子。
> library(ggplot2)
> mtcars$am <- factor(mtcars$am, levels=c(0,1), labels=c('Automatic', 'Manual'))
> mtcars$cyl <- factor(mtcars$cyl, levels=c(4,6,8), labels=c('cyl-4', 'cyl-6','cyl-8'))
> ggplot(data=mtcars, aes(x=cyl, y=mpg, fill=am)) + # 使用am填充分組
+ geom_boxplot() +
+ labs(title='ggplot2', x='cyl', y='MPG') +
+ theme(plot.title = element_text(hjust = 0.5))
在這里我們使用箱線圖展示了cyl和mpg的關(guān)系,并使用am進(jìn)行了二次分組,分組方式為填充顏色表示(fill=am
)。
最后我們?cè)賮砜匆粋€(gè)使用了多個(gè)幾何函數(shù)的圖形,該圖形使用的是Salaries數(shù)據(jù)集。
> data(Salaries,package='car')
> ggplot(Salaries, aes(x=rank, y=salary)) +
+ geom_boxplot(fill='cornflowerblue', color='black',notch=TRUE) + # 添加箱線圖
+ geom_point(position='jitter',color='blue',alpha=0.5) + # 添加打散(jitter)了的散點(diǎn)圖
+ geom_rug(sides='l',color='green') # 在左側(cè)添加軸須圖
+ labs(title='ggplot2') # 添加標(biāo)題,默認(rèn)添加在左上方
3、分組
通常為了更好地理解數(shù)據(jù),在一個(gè)圖中畫出兩個(gè)或更多組的觀察值通常都是很有幫助的。ggplot2中的分組是通過一個(gè)或多個(gè)帶有諸如性狀、顏色、填充、尺寸和線條類型的視覺特征的分組變量來完成的。ggplot2中的aes()
函數(shù)負(fù)責(zé)分配變量(圖形的視覺特征),所以這是一個(gè)分配分組變量的自然地方。
這里我們將繼續(xù)使用Salaries數(shù)據(jù)集,首先來查看下薪水是如何隨學(xué)術(shù)等級(jí)而變化的。代碼:
> ggplot(data=Salaries, aes(x=salary, fill=rank)) + # 根據(jù)學(xué)術(shù)等級(jí)rank進(jìn)行分類
+ geom_density(alpha=0.3) # 添加密度圖
從圖中可以看到不同學(xué)術(shù)等級(jí)的薪水雖然有重疊,但仍能看到隨著學(xué)術(shù)水平的增加薪水提高了。接下來,我們通過性別和學(xué)術(shù)等級(jí)分組,繪制獲得博士學(xué)位年數(shù)與薪水的關(guān)系,代碼:
> ggplot(Salaries, aes(x=yrs.since.phd, y=salary, color=rank, shape=sex)) +
# 這里使用了兩個(gè)分組變量sex和rank,在圖中分別通過不同的顏色和不同的形狀表示
+ geom_point()
最后,選項(xiàng)可以通過不同的方式使用,這取決于他們發(fā)生在
aes()
函數(shù)內(nèi)部還是外部。讓我們比較下面的一段代碼繪制的圖形:
> p1<-ggplot(Salaries, aes(x=rank, fill=sex)) + geom_bar()
> p2<-ggplot(Salaries, aes(x=rank)) + geom_bar()
> p3<-ggplot(Salaries, aes(x=rank,fill='red')) + geom_bar()
> p4<-ggplot(Salaries, aes(x=rank)) + geom_bar(fill='red')
> library(gridExtra)
> grid.arrange(p1,p2,p3,p4,ncol=4) # 組合圖形
在第一個(gè)圖(p1)中,sex變量通過條形圖中的填充顏色來展示。在第二個(gè)圖(p2)中,沒有設(shè)置分組變量也沒有設(shè)置填充顏色,只繪制了各個(gè)rank的數(shù)量。第三個(gè)圖(p3)中,ggplot2假定‘red’是變量名,結(jié)果得到的結(jié)果與圖2基本相同。第四個(gè)圖(p4),使用紅色來填充圖形。
4、刻面
如果組在圖中并排出現(xiàn)而不是重疊為單一的圖形,關(guān)系就是清晰的。我們可以使用facet_wrap()
和facet_grid()
函數(shù)創(chuàng)建網(wǎng)格圖形(也稱刻面圖)。這些函數(shù)的使用方法如下,其中var,rowvar,colvar是因子:
語法 | 結(jié)果 |
---|---|
facet_wrap(~var, ncol=n) | 將每個(gè)var水平排列成n列的獨(dú)立圖 |
facet_wrap(~var, nrow=n) | 將每個(gè)var水平排列成n行的獨(dú)立圖 |
facet_grid(rowvar~colvar) | rowvar和colvar組合的獨(dú)立圖,其中rowvar表示行,colvar表示列 |
facet_grid(rowvar~.) | 每個(gè)rowvar水平的獨(dú)立圖,配置成一個(gè)單列 |
facet_grid(.~colvar) | 每個(gè)colvar水平的獨(dú)立圖,配置成一個(gè)單行 |
接下來我們使用mtcars數(shù)據(jù),以am和cyl作為分組變量對(duì)mpg進(jìn)行分組繪制直方圖。
library(ggplot2)
mtcars$am <- factor(mtcars$am, levels=c(0,1), labels=c('Automatic', 'Manual'))
mtcars$cyl <- factor(mtcars$cyl, levels=c(4,6,8), labels=c('cyl-4', 'cyl-6','cyl-8'))
ggplot(data=mtcars, aes(x=mpg)) +
geom_histogram(fill='green') +
facet_wrap(~cyl, nrow=1) # 使用cyl作為分組變量將mpg分組繪制
library(ggplot2)
mtcars$am <- factor(mtcars$am, levels=c(0,1), labels=c('Automatic', 'Manual'))
mtcars$cyl <- factor(mtcars$cyl, levels=c(4,6,8), labels=c('cyl-4', 'cyl-6','cyl-8'))
ggplot(data=mtcars, aes(x=mpg)) +
geom_histogram(fill='green') +
facet_grid(am~cyl) # 同時(shí)使用am和cyl作為分組變量,交叉分組
5、擬合曲線
選項(xiàng) | 描述 |
---|---|
method | 使用的平滑函數(shù)。可選的值包括lm, glm, smooth,rlm和gam,分別對(duì)應(yīng)線性,廣義線性,loess,健壯線性和廣義相加模型。默認(rèn)為smooth |
formula | 在光滑曲線中使用的公式,例如y~x ,y~log(x) ,y~poly(x, n) |
se | 繪制置信區(qū)間。默認(rèn)為TRUE |
level | 使用的置信區(qū)間水平(默認(rèn)為95%) |
fullrange | 指定擬合應(yīng)涵蓋全圖(TRUE)或僅僅是數(shù)據(jù)(FALSE),默認(rèn)為FALSE |
本部分我們將分析一下添加平滑曲線(線性,非線性和非參數(shù))到散點(diǎn)圖中的方法。我們可以使用geom_smooth()
函數(shù)來添加一系列平滑曲線和置信區(qū)域。函數(shù)的參數(shù)見下表:
選項(xiàng) | 描述 |
---|---|
method | 使用的平滑函數(shù)。可選的值包括lm, glm, smooth,rlm和gam,分別對(duì)應(yīng)線性,廣義線性,loess,健壯線性和廣義相加模型。默認(rèn)為smooth |
formula | 在光滑曲線中使用的公式,例如y~x ,y~log(x) ,y~poly(x, n) |
se | 繪制置信區(qū)間。默認(rèn)為TRUE |
level | 使用的置信區(qū)間水平(默認(rèn)為95%) |
fullrange | 指定擬合應(yīng)涵蓋全圖(TRUE)或僅僅是數(shù)據(jù)(FALSE),默認(rèn)為FALSE |
這里使用Salaries數(shù)據(jù)集,我們先檢驗(yàn)博士畢業(yè)年數(shù)和薪水之間的關(guān)系。在這個(gè)例子中,我們使用帶有95%置信區(qū)間的非參數(shù)光滑曲線(loess)。暫時(shí)忽略學(xué)術(shù)等級(jí)和性別,代碼:
> data(Salaries, package='car')
> library(ggplot2)
> ggplot(data=Salaries, aes(x=yrs.since.phd, y=salary)) +
+ geom_point() +
+ geom_smooth(color='red')
圖形顯示,隨著博士畢業(yè)年數(shù)的增加,薪水先增加后來又會(huì)降低。
接下來,我們按性別擬合一個(gè)二次多項(xiàng)式回歸(一個(gè)彎曲):
> ggplot(data=Salaries, aes(x=yrs.since.phd, y=salary, linetype=sex, color=sex, shape=sex)) +
+ geom_smooth(method=lm, formula=y~poly(x,2),se=FALSE,size=1) +
+ geom_point(size=2)
正如前面第一部分我們說的那樣,當(dāng)使用全局的數(shù)據(jù)源(在ggplot中設(shè)置)時(shí),我們會(huì)擬合出分類數(shù)條曲線。這里我們分別對(duì)女性和男性的薪水隨博士畢業(yè)年限的變化擬合了兩條曲線。
6、修改ggplot2圖形的外觀
在R基本繪圖中,我們可以使用par()
函數(shù)定義全局參數(shù)。在ggplot2中提供了特定的函數(shù)來改變圖形外觀。
6.1 坐標(biāo)軸
ggplot2在創(chuàng)建圖形時(shí)會(huì)自動(dòng)創(chuàng)建刻度線、刻度標(biāo)記和坐標(biāo)軸標(biāo)簽,有時(shí)我們可能想自定義這些圖形。前面我們已經(jīng)看到了labs()
函數(shù)可以用來添加標(biāo)題和軸標(biāo)題,本節(jié)中我們將自定義軸標(biāo)簽,自定義軸標(biāo)簽的函數(shù)如下:
函數(shù) | 選項(xiàng) |
---|---|
scale_x_continous()、scale_y_continous | breaks=指定刻度標(biāo)記,labels=指定刻度標(biāo)記標(biāo)簽,limits=控制要展示的值得范圍 |
scale_x_discret()和scale_y_discret() | breaks=對(duì)因子的水平進(jìn)行放置和排序,labels=指定這些水平的標(biāo)簽,limits=表示那些水平應(yīng)該展示 |
coord_flip() | 顛倒X軸和Y軸 |
可以看到,ggplot2的函數(shù)區(qū)分x軸和y軸,以及軸線是否代表一個(gè)連續(xù)或離散變量(因子)。
下面我們將這些函數(shù)應(yīng)用到一個(gè)分組箱線圖中,其中包含按學(xué)術(shù)等級(jí)和性別分組的薪資水平,代碼:
> ggplot(data=Salaries, aes(x=rank, y=salary, fill=sex)) +
+ geom_boxplot() +
+ scale_x_discrete(breaks=c('AsstProf', 'AssocProf', 'Prof'),
labels=c('Assistant\nProfessor', 'Associate\nProfessor', 'Full\nProfessor')) +
+ scale_y_continuous(breaks=c(50000, 100000, 150000, 200000),
labels=c('$50K','$100K','$150K','$200K')) +
+ labs(title='Faculty Salary by Rank and Sex', x='rank',y='salary')
可以很明顯的看到,平均收入隨著學(xué)術(shù)排名的上升而上升,在每個(gè)學(xué)術(shù)等級(jí)中男性的薪資水平高于女性。
6.2 圖例
圖例是指如何用顏色、形狀尺寸等視覺特性表示數(shù)據(jù)特征的指南。ggplot2包能自動(dòng)生成圖例,而且很多時(shí)候能滿足我們的需求;但在某些時(shí)候,我們可能需要對(duì)其進(jìn)行自定義。標(biāo)題和位置是最常用的定制特征。
當(dāng)更改圖例的標(biāo)題時(shí),必須考慮圖例是否基于顏色、尺寸、形狀或他們的組合。在6.1節(jié)中,圖例代表fill,因此我們可以通過將fill='mytitle'
加到labs()
函數(shù)中來改變標(biāo)題。標(biāo)題的位置由theme()函數(shù)中的legend.position選項(xiàng)控制。可能的值包括'left'、'right'(默認(rèn))、'top'和'bottom'。我們也可以在圖中給定位置指定一個(gè)二元向量。下面我們對(duì)6.1節(jié)中的圖進(jìn)行更改,增加一個(gè)分類因子color=discipline
,并改變圖例的標(biāo)題和位置。
> ggplot(data=Salaries, aes(x=rank, y=salary, fill=sex, color=discipline)) +
+ geom_boxplot() +
+ scale_x_discrete(breaks=c('AsstProf', 'AssocProf', 'Prof'),
labels=c('Assistant\nProfessor', 'Associate\nProfessor', 'Full\nProfessor')) +
+ scale_y_continuous(breaks=c(50000, 100000, 150000, 200000),
labels=c('$50K','$100K','$150K','$200K')) +
+ labs(title='Faculty Salary by Rank and Sex', x='rank',y='salary',color='Discip', fill='Gender') +
### labs()中的color='Discip'和fill='Gender'分別表示color和fill兩個(gè)分類的圖例的名稱
+ theme(legend.position=c(0.1,0.8)) # 設(shè)置圖例位置
c(0.1,0.8)
分別表示距離左側(cè)邊緣10%和底部邊緣80%的部分。如果想刪除圖例則可以使用legend.position='none'
。
6.3 標(biāo)尺
ggplot2包使用標(biāo)尺把數(shù)據(jù)映射到可視化的空間中。標(biāo)尺既可以應(yīng)用到連續(xù)的變量,也可以應(yīng)用到離散的變量。下面我們使用mtcars數(shù)據(jù)集,將disp變量映射到圖形中點(diǎn)的大小,代碼:
> ggplot(mtcars, aes(x=wt, y=mpg, size=gear)) + # gear映射到散點(diǎn)的大小
+ geom_point(shape=21, color='black', fill='cornsilk') +
+ labs(x='Weight', y='Miles Per Gallon', title='Bubble Chart', size='Gear')
scale_color_manual()
函數(shù)來手動(dòng)設(shè)定三個(gè)cyl的點(diǎn)的顏色。
> mtcars$cyl <- factor(mtcars$cyl, levels=c(4,6,8), labels=c('cyl-4', 'cyl-6','cyl-8'))
> ggplot(mtcars, aes(x=wt, y=mpg, color=cyl)) +
+ geom_point(shape=21) +
+ labs(x='Weight', y='Miles Per Gallon') +
+ scale_color_manual(values=c('red','blue','green'))
scale_color_brewer()
和scale_fill_brewer()
函數(shù)來指定顏色集。
6.4 主題
theme()
函數(shù)中的選項(xiàng)可以讓我們調(diào)整字體、北京、顏色和網(wǎng)格線等。主題可以使用一次,也可以保存起來應(yīng)用到多個(gè)圖中。
library(ggplot2)
data(Salaries, package='car')
mytheme<-theme(plot.title=element_text(face='bold.italic',size=14,color='brown',hjust=0.5), # 指定圖標(biāo)題的字體以及位置
axis.title=element_text(face='bold.italic',size=10,color='brown'), # 設(shè)置軸標(biāo)題的字體大小等
axis.text=element_text(face='bold.italic',size=9,color='darkblue'), # 軸標(biāo)簽字體設(shè)置
panel.background=element_rect(fill='white',color='darkblue'), # 背景設(shè)置
panel.grid.major.y=elemnt_line(color='grey',linetype=1), # 設(shè)置網(wǎng)格線
panel.grid.minor.y=element_line(color='grey', linetype=2), # 設(shè)置網(wǎng)格線
panel.grid.minor.x=element_blank()) # 垂直網(wǎng)格不輸出
ggplot(Salaries, aes(x=rank,y=salary,fill=sex)) +
geom_boxplot() +
labs(title='Salary by Rank and Sex',x='RANK',y='Salary') +
mytheme
7、組合圖
在基礎(chǔ)繪圖中,我們使用par()
函數(shù)的mfrow和mfcol參數(shù)和layout()
來將多個(gè)圖形組合起來。將多個(gè)ggplot圖形組在一起最簡單的方式是使用gridExtra包中的grid.arrange()
函數(shù),使用前需先安裝這個(gè)包。
下面我們將三個(gè)ggplot圖形合并到一個(gè)圖中,代碼:
> p1<-ggplot(data=Salaries, aes=(x=rank)) + geom_bar()
> p1<-ggplot(data=Salaries, aes(x=rank)) + geom_bar()
> p2<-ggplot(data=Salaries, aes(x=sex)) + geom_bar()
> p3<-ggplot(data=Salaries, aes(x=yrs.since.phd, y=salary)) + geom_point()
> library(gridExtra)
> grid.arrange(p1, p2, p3)
> grid.arrange(p1, p2, p3, ncol=3)
8、保存圖形
保存圖形能使用基礎(chǔ)繪圖的方法,但ggsave()
函數(shù)能更為方便地保存它。它的選項(xiàng)包括保存那幅圖形,保存位置以及保存形式。
myplot<-ggplot(data=mtcars, aes(x=mpg)) + geom_histogram()
ggsave(file='filename.tiff', plot=myplot, width=5, height=4)
我們可以通過將文件名的擴(kuò)展格式設(shè)置為不同的格式來以不同的方式保存。如果忽略plot=
選項(xiàng),最近創(chuàng)建的圖形會(huì)被保存。