實用教程!R語言 ggplot2 繪圖入門

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。

很多人不明白所謂的映射。其實映射,通俗來講,就是告訴軟件,這幅圖所涉及到的變量,并且指出每個變量的用途。比如,x=gender,指的是x軸是性別;y=age,指的是y軸表示年齡大小,shape=location,指的是不同地區圖標的形狀不一樣(比如城市用星號,農村用三角)

·???選擇一個合適的圖形類型,函數名以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,

?mapping =aes(

???x =?gdpPercap,

???y =?lifeExp))

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)?

labs(

???x ="人均GDP",

???y ="期望壽命(年數)",

???title ="經濟增長與期望壽命",

???subtitle ="數據點為每個國家每年",

???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)。

利用繪圖語法既可以做出常見的統計圖形, 也可以做出各種新穎的圖形, 當然, 就像語法正確的語句不一定有意義, 用繪圖語法做得新穎圖形不一定有實際意義, 還是要按照可視化的一般原則做出能說服讀者的圖形

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容