R語言最擅長繪圖。R語言最擅長的繪圖包是ggplot2,由於很多朋友沒有接觸過ggplot2,必須要對其語言方式有個初步的認識。所以入門學習是必須的。公眾號先前若干篇文章已經介紹ggplot2繪圖的基本方法(具體可以關注文末連結),為推動學習,今天介紹再次系統的一番。
ggplot2包是R的一個作圖用的最精彩的擴展包,它實現了「圖形的語法」,將一個作圖任務分解為若干個子任務,只要完成各個子任務就可以完成作圖。在作常用的圖形時,只需要兩個步驟:首先將圖形所展現的數據輸入到ggplot()函數中,然後調用某個geom_xxx()函數,指定圖形類型,如散點圖、曲線圖、盒形圖等。
如果需要進一步控制圖形細節,只要繼續調用其它函數,就可以控制變量值的表現方式(scale)、圖例、配色等。這使得我們很容易做出基本的圖形,在有需要時再深入學習,做出更為滿意的圖形。
與基本R中的作圖系統相比, ggplot2的作圖有規律可循,作圖結果直接達到出版印刷質量,除了可以按照一些既定模式做出常見種類的圖形,也很容易將不同圖形種類組合在一起,或者設計新穎的圖形。基本R的作圖結果通常不夠美觀,如果要將不同種類圖形組合在一起比較困難,對設計新的圖形類型支持也不夠好。
ggplot2 的繪圖理念與基礎的繪圖有很大的不同,基礎的繪圖就好像是先鋪好畫布,然後在畫布上畫圖,是一個平面的,而ggplot2打破了這種畫圖的方式 ,採用了圖層的概念進行畫圖,先畫好基礎圖,然後再往上一層一層的疊加圖層,所以在進行ggplot2畫圖的時候,代碼中會有大量的「+」,這就是對於圖層的疊加。本章將大致的給大家介紹醫學數據應用ggplot2基本的結構。
ggplot2 圖層元素
1.數據(data):將要可視化的數據
2.映射(aes):數據中的變量值
3.幾何對象(geom):如bar條形圖,point散點圖
4. 統計變換(stats):對數據進行計算
5.標度(scale):變量以什麼形狀、顏色映射到圖形上
6. 分面(facet):將數據拆開,進行分層畫圖
7. 主題(theme):主題設定,與數據無關的圖層可以通過這個函數實現。
8. 注釋 (annotate): 對圖形增加文字類的注釋
ggplot()圖層
ggplot ()圖層包括數據和映射。ggplot函數相當於一幅基本的畫布,畫者在上面繪製好坐標軸,設置好基本的格局和色彩、線條。
geom_XXX() 圖層
geom_XXX() 指的是我們要繪製的圖形類型,常見包括以下:
geom_point()繪製散點圖
geom_bar()繪製條形圖
geom_line()繪製線圖
geom_histogram()繪製直方圖
geom_boxplot() 繪製箱式圖
geom_density() 繪製概率密度函數
scale_ XXX 圖層
scale_ XXX 標度是一種函數,size對大小進行調整,shape對形狀進行調整,fill、col對顏色進行調整,可根據自己喜好調整
ggplot(data =數據 , aes(x =變量1 , y = 變量2,col=變量3)) +
geom_point(stat = 'count',position=」dodge」)+ #計數、並排
scale_fill_manual(values = c("顏色1","顏色2"))
facet_grid() 圖層
facet_grid(...) 對圖層進行分面,數據分成多個子集進行繪圖
ggplot(data =數據 , aes(x =變量1 , y = 變量2,col=變量3)) +
geom_point(stat = 'count',position=」dodge」)+
scale_colour_manual(values = c("顏色1","顏色2"))+
facet_grid(變量4~變量5) #要求變量屬於分類變量,分成多行多列的圖
theme() 圖層
theme() 是主題修改,是一個對繪圖精雕細琢的過程, 主要對標題、坐標軸標籤、圖例標籤等文字調整, 以及網格線、背景、軸的顏色搭配。
theme(plot.title = element_text(size = , color =, hjust = , face = ))
ggplot2的作圖一般步驟為:
· 準備數據,一般為數據框,且一般為長表,即每個觀測時間佔一行,每個觀測變量佔一列。
· 載入R包,R包括可以通過tidyverse包整體載入。
· 將數據輸入到ggplot()函數中,並指定參與作圖的每個變量分別映射到哪些圖形特性,比如映射為x坐標、y坐標、顏色、形狀等。這些映射稱為aesthetic mappings或aesthetics。
· 選擇一個合適的圖形類型,函數名以geom_開頭,如geom_point()表示散點圖。圖形類型簡稱為geom。將ggplot()部分與geom_xxx()部分用加號連接。到此已經可以作圖,下面的步驟是進一步的細化設定。
· 設定適當的坐標系統,如coord_cartesian(), scale_x_log10()等。仍用加號連接。
· 設定標題和圖例位置等,如labs()。仍用加號連接。
這個流程的一個大致的模板為:
p <-ggplot(data=<輸入數據框>,
mapping=aes(<維度>=<變量名>,
<維度>=<變量名>, <...>))
p +geom_<圖形類型>(<...>) +
scale_<映射>_<類型>(<...>) +
coord_<類型>(<...>) +
labs(<...>)
其中<...>表示額外的選項。變量p包含做出的圖形的所有數據與設定,變量名可以任意取。
我接下來講引用R語言自帶資料庫,以散點圖為例,進行ggplot2繪圖。
本文數據集來自gapminder擴展包的gapminder數據集,有若干個國家不同年份的一些數據,包括所屬洲、期望壽命、人口數、人均GDP。有1704個觀測和6個變量。資料庫的變量包括country(國家) 、continent(洲)、year(年)、lifeExp(期望壽命)、pop(人口數)、gdpPercap(人均GDP)
library(gapminder)
head(gapminder, 6)
# A tibble: 6 x 6
country continent year lifeExp pop gdpPercap
<fct> <fct> <int> <dbl> <int> <dbl>
1 Afghanistan Asia 1952 28.8 8425333 779.
2 Afghanistan Asia 1957 30.3 9240934 821.
3 Afghanistan Asia 1962 32.0 10267083 853.
4 Afghanistan Asia 1967 34.0 11537966 836.
5 Afghanistan Asia 1972 36.1 13079460 740.
6 Afghanistan Asia 1977 38.4 14880372 786.
這個數據集有多個國家在多個年份的期望壽命與人均GDP值,作期望壽命對人均GDP的散點圖,每個國家的每個年份作為一個點。散點圖最重要的映射是x軸與y軸兩個維度。
1. 最基本的散點圖
首先調用繪圖基本函數ggplot()函數,指定數據集,將人均GDP映射到x軸,將期望壽命映射到y軸,結果保存為一個R變量:
p <-ggplot(data = gapminder,
mapping =aes(
x = gdpPercap,
y = lifeExp))
ggplot()的調用中,可以省略data =, mapping =, x =, y =,寫成:
p <-ggplot(gapminder, aes(gdpPercap, lifeExp))
ggplot函數,相當於一幅基本的畫布,畫者在上面繪製好坐標軸,設置好基本的格局和色彩、線條。
在如上指定了數據和映射後,只要用geom_xxx()指定一個圖形類型,並與ggplot()的結果用加號連接就可以作圖了,如:
p +geom_point()
x、y軸是最常見的映射,也可以將變量映射為顏色、符號、線型等,這時不需要指定具體的顏色、符號、線型,而是將變量映射為這些圖形元素類型。
2. 更多的美圖
指定數據集、指定映射、選擇適當的圖形類型就可以做出基本的圖形,隨後可以逐步對坐標系、坐標系刻度、標籤與圖例、配色等進行改善。實際上,ggplot2包已經提供了十分合理的預設值,用戶只要進行一些必要的改動即可。
作圖步驟之間用加號連接,這是ggplot包特有的語法。例如,用相同的映射基於geom_smooth() 做出擬合曲線圖:
p +geom_smooth()
## `geom_smooth()` using method ='gam' and formula 'y ~ s(x, bs = "cs")'
用相同的映射做出散點圖併疊加擬合曲線圖:
p +geom_point() +geom_smooth()
## `geom_smooth()` using method ='gam' and formula 'y ~ s(x, bs = "cs")'
geom_smooth()的默認設置調用了gam()函數來擬合曲線,可以用geom_smooth()的參數選擇不同的擬合方法,如直線擬合:
p +geom_point() +geom_smooth(method="lm")
注意geom_xxx()函數計算所需的變量值是從ggplot()函數保存在變量p中的信息提取的。
在以上的所有圖形中, x軸變量(人均GDP)分布非正態,嚴重右偏,使得大多數散點重疊地分布在直角坐標系的左下角。將x軸用對數刻度可以改善,函數為scale_x_log10():
p +geom_point() +
geom_smooth(method="gam") +
scale_x_log10()
廣義可加模型擬合的曲線基本是一條直線。注意,對數刻度實際上是對原始數據進行對數變換,而geom_smooth()的擬合計算是在對數變換之後進行的。
剛剛的圖形的橫坐標軸刻度不太友好,可以調用scales擴展包的適當函數進行改善,作為scale_x_log10()的labels選項:
p +geom_point() +
geom_smooth(method="gam") +
scale_x_log10(labels=scales::dollar)
scale_xxx()的labels選項指定如何標出坐標刻度數字,參數值是一個函數對象,如果scales包中找不到適當的功能,可以自定義一個函數將數值轉換為字符串。 scales包提供了comma, date, dollar, math,number, ordinal, pvalue, scientific, time 等坐標刻度值轉換函數。
4. 在geom_point()和geom_smooth()加點簡單元素
geom_xxx()函數接受許多關於顏色、透明度、符號、線型的設置參數。比如,下面的程序指定了散點的透明度,以及散點圖的顏色的粗細:
p <-ggplot(data=gapminder,p +geom_point(color="chartreuse4",alpha=0.5) + geom_smooth(method="loess") + scale_x_log10(labels=scales::dollar)當然,也可以對geom_smooth()玩一把
p +geom_point(color="chartreuse4",alpha=0.5) +
geom_smooth(color="cadetblue1", se =FALSE, size =2, alpha =0.3)
程序中size指定了線的以毫米為單位的粗細, se = FALSE關閉了置信區間顯示。用alpha =設置了透明度,取0和1之間的值,數值越小越透明。在有許多個點時適當設置透明度可以比較好地顯示出重疊的點,重疊點越多點的顏色越深。雖然這裡設置了固定的透明度,也可以在aes()中將透明度alpha映射到某個變量,使得該變量值大小用點的透明度表示。
畫線時可以用linetype參數指定線型, 0表示實線, 1到6分別表示不同的虛線線型。
最後,來一個下面用labs()函數給圖形加上適當的標題:
p +geom_point(color="chartreuse4",alpha=0.5) + geom_smooth(color="cadetblue1", se =FALSE, size =2, alpha =0.3) caption ="數據來源: gapminder" )3.顏色、符號、線型等映射
在ggplot()函數的mapping參數的aes()設定中將變量映射到x、y軸,顏色、符號、線型等圖形元素類型,也可以作為圖形設置將某些圖形元素設置為固定值。
例如,用不同顏色表示不同大洲,就是將continent變量映射到color:
p <-ggplot(data=gapminder,
mapping =aes(
x = gdpPercap,
y = lifeExp,
color = continent))
程序中僅指定了將大洲映射到顏色維,並不具體指定所用的顏色。
作帶有局部多項式曲線擬合的散點圖:
p +geom_point() +
geom_smooth(method="loess") +
scale_x_log10(labels=scales::dollar)
可以看出,不同散點用了不同顏色表示其continent變量的值,五個大洲分別進行了曲線擬合,曲線使用了不同顏色但置信域顏色相同,使得難以認讀。在圖形右側自動生成了顏色與continent變量值的對應關係圖例。
下面的圖形仍分不同大洲作曲線擬合,並將置信區間陰影的顏色也用不同大洲區分,方法是在aes()中將color和fill都指定為變量continent:
p <-ggplot(data=gapminder,
mapping =aes(
x = gdpPercap,
y = lifeExp,
color = continent,
fill = continent))
p +geom_point() +
geom_smooth(method="loess") +
scale_x_log10(labels=scales::dollar)
4. 在geom_xxx() 映射變量
在前面的一個例圖中,在ggplot()函數中將color和fill映射到了continent變量,使得不僅散點顏色代表了不同大洲,還使得每個大洲單獨擬合了曲線。如果希望所有大洲擬合同一條曲線怎麼辦?
在必要時,可以在geom_xxx()函數中用mapping = aes(<...>)單獨指定變量映射。例如,下面的程序在geom_point()中將不同大洲映射為不同顏色,而不影響geom_smooth()中的顏色以及分組:
p <-ggplot(data=gapminder,
mapping =aes(
x = gdpPercap,
y = lifeExp))
p +geom_point(mapping =aes(color = continent)) +
geom_smooth(method="loess") +
scale_x_log10(labels=scales::dollar)
也可以將一個分類變量映射到不同繪圖符號。例如,取gapminder 2007年數據子集,將大洲映射到符號(shape):
p <- ggplot(data = filter(gapminder,year==2007),
mapping = aes(
x = gdpPercap,
y = lifeExp))
p + geom_point(mapping =aes(shape = continent), alpha = 0.4, size = 4) +
scale_x_log10(labels=scales::dollar)
這種映射僅適用於點數比較少的情況,太多密密麻麻不好看(為此我們用了filter函數抽取2007年的數據),還用了size參數指定符號的大小(單位:毫米)。如果所有點使用同一符號並需要指定符號,可以在geom_point()中用shape參數指定,可以用0到25的整數值表示,比如19為實心點,也可以用字符串符號名稱表示,如"circle"表示實心點。參見ggplot2幫助目錄中的vignette ggplot2:ggplot2-specs。
也可以將連續變量映射為漸變色。除了表示二元函數的等值線圖以外這種方法並不利於讀者認讀。
例如,將人口數取自然對數映射為漸變色:
p <-ggplot(data=gapminder,
mapping =aes(
x = gdpPercap,
y = lifeExp,
color =log(pop)))
p +geom_point() +
geom_smooth(method="loess") +
scale_x_log10(labels=scales::dollar)
5.小圖
前面所有國家的圖包含了過多的曲線, 使得圖形表現得很擁擠。可以將一個作圖區域拆分成若干個小塊, 稱為小圖(facet), 按照某一個或兩個分類變量的不同值將數據分為若干個子集, 每個數據子集分別在小圖上作圖。
對於上面的例子, 可以將每個大洲的圖形分別放置在一個小圖上。小圖不是一種變量映射, 而是一種圖形擺放方法, 所以不設置在aes()函數內, 而是用facet_wrap()函數規定。 程序如:
p <-ggplot(data=gapminder,
mapping =aes(
x = gdpPercap,
y = lifeExp,
color= continent))
p +geom_point() +
geom_smooth(method="loess") +
scale_x_log10(labels=scales::dollar)+
facet_wrap(~ continent, ncol = 2)
區分不同小圖的標籤寫在每個小圖的上方。可以用facet_wrap()參數strip_position和參數switch調整標籤的上下左右。
小圖之間默認公用了橫坐標和縱坐標且坐標範圍保持一致。如果不保持一致, 讀者可能會有誤解。但是x軸或y軸映射為分類變量且不同小圖的分類完全不同時, 可以令各小圖中該軸的取值不統一。facet_wrap()選項scales默認為"fixed", 即所有小圖的x軸、y軸都範圍一致, 取"free_x"則允許各小圖的x軸不統一, "free_y"允許各小圖的y軸不統一, "free"允許各小圖的x軸和y軸都不統一。
在facet_wrap()中可以用ncol參數指定小圖的列數, 用nrow指定小圖的行數。各個小圖的次序應該設定為一定的合理次序, 比如用來分類的變量本身有序, 或者令各小圖中的數據值有一定的增減次序。
6.總結
ggplot2的不僅僅是能夠做一些固定格式的圖形, 而是按照一種圖形語法構建圖形。小圖功能可以將數據集分成若干子集作多幅小圖, 每幅小圖中, 有可以分層, 每層有不同類型的圖, 各層疊加顯示在一起。所以,分層語法作圖結構如下:
有一個主要的數據集, 以及從數據集變量到坐標位置、顏色、填充、大小、符號等的映射關係(aesthetics);
有一到多個圖層, 比如散點圖和平滑曲線圖層, 每個圖層有幾何對象、必要的統計變換、位置調整, 還可以有額外的數據集以及額外的映射關係;
對每個映射關係有一個刻度(scaling), 對x、y維,一般需要線性變換,偶爾用到對數變換之類的其它變換, 顏色、填充等維度需要一些複雜的對應關係。無特殊需要時只要使用默認刻度;
有一個坐標系統, 如直角坐標系、極坐標系、球面坐標系等, 一般只要使用默認的坐標系統;
可以劃分小圖(facetting)。
利用繪圖語法既可以做出常見的統計圖形, 也可以做出各種新穎的圖形, 當然, 就像語法正確的語句不一定有意義, 用繪圖語法做得新穎圖形不一定有實際意義, 還是要按照可視化的一般原則做出能說服讀者的圖形