最近把之前的《R數(shù)據(jù)科學》的筆記整理一下式矫,大概每篇文章整理2-3章捺檬,這本書有中英文兩版,不知道為什么中文版比英文版少了一章状知,而且一些關(guān)鍵內(nèi)容也有所刪減秽五,所以大家學習這本書的時候以英文版為準。
電子書下載地址:《R4ds》
源代碼地址:https://github.com/hadley/r4ds
作者簡介:
哈德利?威克姆(Hadley Wickham)
RStudio首席科學家饥悴,統(tǒng)計學家坦喘,斯坦福大學盲再、奧克蘭大學、萊斯大學兼職統(tǒng)計學教授瓣铣。已被下載數(shù)百萬次的ggplot2等多款知名R包的開發(fā)者答朋,一直致力于讓普羅大眾更容易上手數(shù)據(jù)分析,被R社區(qū)譽為“改變了R的人”棠笑。另著有《R包開發(fā)》等書梦碗。
加勒特?格羅勒芒德(Garrett Grolemund)
RStudio數(shù)據(jù)科學家,知名R培訓師腐晾,曾受邀在Google叉弦、eBay等諸多公司講授R語言和數(shù)據(jù)科學丐一,在DataCamp開授的R相關(guān)課程備受R開發(fā)者喜愛藻糖。另著有《R語言入門與實踐》。
第一章:使用ggplot2進行數(shù)據(jù)可視化
1.1 簡介
準備工作
本章重點討論tidyverse 的一個核心R 包——ggplot2库车。為了訪問本章用到的數(shù)據(jù)集巨柒、幫助頁面和函數(shù),需要先運行以下代碼來加載tidyverse
install.packages("tidyverse")
library(tidyverse)
1.2 第一步
我們使用第一張圖來回答問題:大引擎汽車比小引擎汽車更耗油嗎柠衍?你可能已經(jīng)有了答案洋满,但應該努力讓答案更精確一些。引擎大小與燃油效率之間是什么關(guān)系珍坊?是正相關(guān)牺勾,還是負相關(guān)?是線性關(guān)系阵漏,還是非線性關(guān)系驻民?
1.2.1 mpg數(shù)據(jù)框
你可以使用ggplot2 包中的mpg 數(shù)據(jù)框(即ggplot2::mpg)來檢驗自己的答案。數(shù)據(jù)框是變量(列)和觀測(行)的矩形集合履怯。mpg 包含了由美國環(huán)境保護協(xié)會收集的38 種車型的觀測數(shù)據(jù)回还。
> mpg
# A tibble: 234 x 11
manufacturer model displ year cyl trans drv cty hwy fl
<chr> <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
1 audi a4 1.8 1999 4 auto~ f 18 29 p
2 audi a4 1.8 1999 4 manu~ f 21 29 p
3 audi a4 2 2008 4 manu~ f 20 31 p
4 audi a4 2 2008 4 auto~ f 21 30 p
5 audi a4 2.8 1999 6 auto~ f 16 26 p
6 audi a4 2.8 1999 6 manu~ f 18 26 p
7 audi a4 3.1 2008 6 auto~ f 18 27 p
8 audi a4 q~ 1.8 1999 4 manu~ 4 18 26 p
9 audi a4 q~ 1.8 1999 4 auto~ 4 16 25 p
10 audi a4 q~ 2 2008 4 manu~ 4 20 28 p
# ... with 224 more rows, and 1 more variable: class <chr>
mpg 中包括如下變量。
? displ:引擎大小叹洲,單位為升柠硕。
? hwy:汽車在高速公路上行駛時的燃油效率,單位為英里/ 加侖(mpg)运提。與燃油效率高的汽車相比蝗柔,燃油效率低的汽車在行駛相同距離時要消耗更多燃油。要想了解更多關(guān)于mpg 的信息民泵,可以使用?mpg 命令打開其幫助頁面癣丧。
1.2.2 創(chuàng)建ggplot圖形
為了繪制mpg 的圖形,運行以下代碼將displ 放在x 軸洪灯,hwy 放在y 軸:
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy))
上圖顯示出引擎大锌茬浴(displ)和燃油效率(hwy)之間是負相關(guān)關(guān)系竟痰。換句話說,大引擎汽車更耗油掏呼。
在ggplot2 中坏快,你可以使用ggplot() 函數(shù)開始繪圖。ggplot() 創(chuàng)建了一個坐標系憎夷,你可以在它上面添加圖層莽鸿。ggplot() 的第一個參數(shù)是要在圖中使用的數(shù)據(jù)集。ggplot(data = mpg)會創(chuàng)建一張空白圖拾给,因為這張圖沒什么意思祥得,所以就不在這里展示了。
函數(shù)geom_point() 向圖中添加一個點層蒋得,這樣就可以創(chuàng)建一張散點圖级及。ggplot2 中包含了多種幾何對象函數(shù),每種函數(shù)都可以向圖中添加不同類型的圖層额衙。
ggplot2 中的每個幾何對象函數(shù)都有一個mapping 參數(shù)饮焦。這個參數(shù)定義了如何將數(shù)據(jù)集中的變量映射為圖形屬性。mapping 參數(shù)總是與aes() 函數(shù)成對出現(xiàn)窍侧,aes() 函數(shù)的x 參數(shù)和y參數(shù)分別指定了映射到x 軸的變量與映射到y(tǒng) 軸的變量县踢。ggplot2 在data 參數(shù)中尋找映射變量,本例中就是mpg伟件。
1.2.3 繪圖模板
將上面的代碼轉(zhuǎn)換為一個可重用的ggplot2 繪圖模板硼啤。要想生成一張圖,將以下代碼中的尖括號部分替換為數(shù)據(jù)集斧账、幾何對象函數(shù)或映射集合即可:
ggplot(data = <DATA>) +
<GEOM_FUNCTION>(mapping = aes(<MAPPINGS>))
1.2.4 練習
(1) 運行g(shù)gplot(data = mpg)谴返,你會看到什么?
一片空白
(2) 數(shù)據(jù)集mpg 中有多少行其骄?多少列亏镰?
234行11列
(3) 變量drv 的意義是什么?使用?mpg 命令閱讀幫助文件以找出答案拯爽。
傳動系的類型索抓,其中f =前輪驅(qū)動,r =后輪驅(qū)動毯炮,4 = 4wd
(4) 使用hwy 和cyl 繪制一張散點圖逼肯。
ggplot(data = mpg) +
geom_point(mapping = aes(x = cyl, y = hwy))
上圖顯示出引擎大小(displ)和燃油效率(hwy)之間是負相關(guān)關(guān)系桃煎。換句話說篮幢,大引擎汽車更耗油。
在ggplot2 中为迈,你可以使用ggplot() 函數(shù)開始繪圖三椿。ggplot() 創(chuàng)建了一個坐標系缺菌,你可以在它上面添加圖層。ggplot() 的第一個參數(shù)是要在圖中使用的數(shù)據(jù)集搜锰。ggplot(data = mpg)會創(chuàng)建一張空白圖伴郁,因為這張圖沒什么意思,所以就不在這里展示了蛋叼。
函數(shù)geom_point() 向圖中添加一個點層焊傅,這樣就可以創(chuàng)建一張散點圖。ggplot2 中包含了多種幾何對象函數(shù)狈涮,每種函數(shù)都可以向圖中添加不同類型的圖層狐胎。
ggplot2 中的每個幾何對象函數(shù)都有一個mapping 參數(shù)。這個參數(shù)定義了如何將數(shù)據(jù)集中的變量映射為圖形屬性歌馍。mapping 參數(shù)總是與aes() 函數(shù)成對出現(xiàn)握巢,aes() 函數(shù)的x 參數(shù)和y參數(shù)分別指定了映射到x 軸的變量與映射到y(tǒng) 軸的變量。ggplot2 在data 參數(shù)中尋找映射變量骆姐,本例中就是mpg镜粤。
1.2.3 繪圖模板
將上面的代碼轉(zhuǎn)換為一個可重用的ggplot2 繪圖模板。要想生成一張圖玻褪,將以下代碼中的尖括號部分替換為數(shù)據(jù)集、幾何對象函數(shù)或映射集合即可:
ggplot(data = <DATA>) +
<GEOM_FUNCTION>(mapping = aes(<MAPPINGS>))
1.2.4 練習
(1) 運行g(shù)gplot(data = mpg)公荧,你會看到什么带射?
一片空白
(2) 數(shù)據(jù)集mpg 中有多少行?多少列循狰?
234行11列
(3) 變量drv 的意義是什么窟社?使用?mpg 命令閱讀幫助文件以找出答案。
傳動系的類型绪钥,其中f =前輪驅(qū)動灿里,r =后輪驅(qū)動,4 = 4wd
(4) 使用hwy 和cyl 繪制一張散點圖程腹。
ggplot(data = mpg) +
geom_point(mapping = aes(x = cyl, y = hwy))
(5) 如果使用class 和drv 繪制散點圖匣吊,會發(fā)生什么情況?為什么這張圖沒什么用處寸潦?
ggplot(data = mpg) +
geom_point(mapping = aes(x = class, y =drv))
(5) 如果使用class 和drv 繪制散點圖色鸳,會發(fā)生什么情況?為什么這張圖沒什么用處见转?
ggplot(data = mpg) +
geom_point(mapping = aes(x = class, y =drv))
車的類型與驅(qū)動類型之間沒有對應關(guān)系命雀,或者說兩者無法發(fā)生關(guān)系。
1.3 圖形屬性映射
The greatest value of a picture is when it forces us to notice what we never expected to see. —John Tukey
下圖中有一組點(顯示為紅色)似乎位于線性趨勢之外斩箫。這些汽車比預期具有更高的里程數(shù)吏砂。
假設(shè)這些汽車是混合動力車撵儿。檢驗這種假設(shè)的一個方法是查看每輛汽車的class值。mpg 數(shù)據(jù)集中的class 變量對汽車進行了分類狐血,比如小型统倒、中型和SUV。如果那些離群點是混合動力車氛雪,那么它們應該分類為小型車房匆,也可能是微型車(注意,這份數(shù)據(jù)是在混合動力車和SUV 流行前收集的)报亩。
可以向二維散點圖中添加第三個變量浴鸿,比如class,方式是將它映射為圖形屬性弦追。圖形屬性是圖中對象的可視化屬性岳链,其中包括數(shù)據(jù)點的大小、形狀和顏色劲件。通過改變圖形屬性的值掸哑,可以用不同的方式來顯示數(shù)據(jù)點(如下圖所示)。因為已經(jīng)使用“value”這個詞來表示數(shù)據(jù)的值零远,所以下面使用“l(fā)evel”(水平)這個詞來表示圖形屬性的值苗分。我們來改變一個點的大小、形狀和顏色來反映不同屬性牵辣。
通過將圖中的圖形屬性映射為數(shù)據(jù)集中的變量摔癣,可以傳達出數(shù)據(jù)的相關(guān)信息。例如纬向,可以將點的顏色映射為變量class择浊,從而揭示每輛汽車的類型:
要想將圖形屬性映射為變量,需要在函數(shù)aes() 中將圖形屬性名稱和變量名稱關(guān)聯(lián)起來逾条。ggplot2 會自動為每個變量值分配唯一的圖形屬性水平(本例中是唯一的顏色)琢岩,這個過程稱為標度變換。ggplot2 還會添加一個圖例师脂,以表示圖形屬性水平和變量值之間的對應關(guān)系担孔。
也可以用同樣的方式將其映射為點的大小。在下面的示例中危彩,每個點的實際大小表示其所屬的類別攒磨。這里我們收到一條警告信息,因為將無序變量(class)映射為有序圖形屬性(size)可不是好主意汤徽。
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, size = class))
Warning message:
Using size for a discrete variable is not advised.
或者我們也可以將class 映射為控制數(shù)據(jù)點透明度的alpha 圖形屬性娩缰,還可以將其映射為點的形狀。
# 上圖
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, alpha = class))
# 下圖
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, shape = class))
SUV 怎么了谒府? ggplot2 只能同時使用6 種形狀拼坎。默認情況下浮毯,當使用這種圖形屬性時,多出的變量值將不會出現(xiàn)在圖中泰鸡。
一旦映射了圖形屬性债蓝,ggplot2 會處理好其余的事情。它會為圖形屬性選擇一個合適的標度盛龄,并創(chuàng)建圖例來表示圖形屬性水平和變量值之間的映射關(guān)系饰迹。ggplot2 不會為x 和y 這兩個圖形屬性創(chuàng)建圖例,而會創(chuàng)建帶有刻度標記和標簽的坐標軸余舶。坐標軸就相當于圖例啊鸭,可以體現(xiàn)出位置和變量值之間的映射關(guān)系。
還可以手動為幾何對象設(shè)置圖形屬性匿值。例如赠制,我們可以讓圖中的所有點都為藍色:
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy), color = "blue")
此時顏色不會傳達關(guān)于變量的信息,只是改變圖的外觀挟憔。要想手動設(shè)置圖形屬性钟些,需要按名稱進行設(shè)置,將其作為幾何對象函數(shù)的一個參數(shù)绊谭。這也就是說政恍,需要在函數(shù)aes() 的外部進行設(shè)置。此外龙誊,還需要為這個圖形屬性選擇一個有意義的值抚垃。
? 顏色名稱是一個字符串。
? 點的大小用毫米表示趟大。
? 點的形狀是一個數(shù)值,如圖1-1 所示铣焊。有些形狀相同逊朽,比如0、15 和22 都是正方形曲伊。
形狀之間的區(qū)別在于color 和fill 這兩個圖形屬性叽讳。空心形狀(0~14)的邊界顏色由color 決定坟募;實心形狀(15~20)的填充顏色由color 決定岛蚤;填充形狀(21~24)的邊界顏色由color 決定,填充顏色由fill 決定懈糯。
練習
(1) 以下這段代碼有什么錯誤涤妒?為什么點不是藍色的?
ggplot(data = mpg) +
geom_point(
mapping = aes(x = displ, y = hwy, color = "blue"))
color在mapping的括號里面,成為了圖形屬性映射
(2) mpg 中的哪些變量是分類變量赚哗?哪些變量是連續(xù)變量她紫?(提示:輸入?mpg 來閱讀這個數(shù)據(jù)集的文檔硅堆。)當調(diào)用mpg 時,如何才能看到這些信息贿讹?
在每一列的下方有<chr>和<int>兩個屬性渐逃,其中<chr>是分類變量,<int>是連續(xù)變量
(3) 將一個連續(xù)變量映射為color民褂、size 和shape茄菊。對分類變量和連續(xù)變量來說,這些圖形屬性的表現(xiàn)有什么不同赊堪?
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, color = hwy))
顏色是一個漸變色面殖,大小也是漸變,形狀會報錯
(4) 如果將同一個變量映射為多個圖形屬性雹食,會發(fā)生什么情況畜普?
兩種屬性會結(jié)合,例如顏色和大小
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy, size = class, color=class))
(5) stroke 這個圖形屬性的作用是什么群叶?它適用于哪些形狀吃挑?(提示:使用?geom_point 命令。)
改變形狀的邊框的大小
(6) 如果將圖形屬性映射為非變量名對象街立,比如aes(color = displ < 5)舶衬,會發(fā)生什么情況?
Error: geom_point requires the following missing aesthetics: x and y
1.4 常見問題
當開始運行R 代碼時赎离,你很可能會遇到問題逛犹。不用擔心,每個人都會遇到問題梁剔。首先虽画,將你需要運行的代碼與書中的代碼進行仔細對比。R 極其挑剔荣病,即使一個字母放錯了位置码撰,也可能會造成問題。確保每個( 都有一個) 與之匹配个盆,并且每個" 后面都跟著另一個"脖岛。有時運行了代碼卻什么也沒有發(fā)生。檢查一下控制臺左側(cè):如果有一個+ 號颊亮,那么說明R 認為你沒有輸入完整的表達式柴梆,正在等待你完成輸入。這種情況下终惑,按Esc 鍵中止當前執(zhí)行的命令就可以重新開始绍在。
創(chuàng)建ggplot2 圖形時的一個常見問題是將+ 號放錯了位置:+ 必須放在一行代碼的末尾,而不是開頭。
1.5 分面
添加額外變量的一種方法是使用圖形屬性揣苏。另一種方法是將圖分割成多個分面悯嗓,即可以顯示數(shù)據(jù)子集的子圖。這種方法特別適合添加分類變量卸察。
要想通過單個變量對圖進行分面脯厨,可以使用函數(shù)facet_wrap()。其第一個參數(shù)是一個公式坑质,創(chuàng)建公式的方式是在~ 符號后面加一個變量名(這里所說的“公式”是R 中的一種數(shù)據(jù)結(jié)構(gòu)合武,不是數(shù)學意義上的公式)。傳遞給facet_wrap() 的變量應該是離散型的涡扼。
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy),stroke=1.5) +
facet_wrap(~ class, nrow = 2)
要想通過兩個變量對圖進行分面稼跳,需要在繪圖命令中加入函數(shù)facet_grid()。這個函數(shù)的第一個參數(shù)也是一個公式吃沪,但該公式包含由~ 隔開的兩個變量名汤善。
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(drv ~ cyl)
如果不想在行或列的維度進行分面,你可以使用. 來代替變量名票彪,例如+ facet_grid(. ~cyl)红淡。
練習
(1) 如果使用連續(xù)變量進行分面,會發(fā)生什么情況降铸?
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(~ cty)
(2) 在使用facet_grid(drv ~ cyl) 生成的圖中在旱,空白單元的意義是什么?它們和以下代碼生成的圖有什么關(guān)系推掸?
雖然空白單元沒有數(shù)據(jù)桶蝎,但也代表了一種組合
ggplot(data = mpg) +
geom_point(mapping = aes(x = drv, y = cyl))
這張圖生成的是沒有意義的圖,每個點代表每種組合谅畅,facet_grid(drv ~ cyl) 生成的圖則將每個組合中displ和 hwy之間的關(guān)系表現(xiàn)了出來登渣。
(3) 以下代碼會繪制出什么圖? . 的作用是什么毡泻?
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(drv ~ .)
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(. ~ cyl)
.的作用決定了分布方向绍豁,如果前面出現(xiàn)、縱向分布牙捉,反之為橫向分布
(4) 查看本節(jié)的第一個分面圖:
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_wrap(~ class, nrow = 2)
與使用圖形屬性相比,使用分面的優(yōu)勢和劣勢分別是什么敬飒?如果有一個更大的數(shù)據(jù)集邪铲,
你將如何權(quán)衡這兩種方法的優(yōu)劣?
使用分面能更好的體現(xiàn)出每個類別displ與hwy的關(guān)系无拗,但是沒辦法比較不同類別之間的區(qū)別
使用屬性能更好的體現(xiàn)整體的關(guān)系带到,但是個體差異不明顯
1.6 幾何對象
兩張圖有同樣的x 變量和y 變量,而且描述的是同樣的數(shù)據(jù)英染。但這兩張圖并不一樣揽惹,它們各自使用不同的可視化對象來表示數(shù)據(jù)被饿。在ggplot2 語法中,我們稱它們使用了不同的幾何對象搪搏。
幾何對象是圖中用來表示數(shù)據(jù)的幾何圖形對象狭握。我們經(jīng)常根據(jù)圖中使用的幾何對象類型來描述相應的圖。例如疯溺,條形圖使用了條形幾何對象论颅,折線圖使用了直線幾何對象,箱線圖使用了矩形和直線幾何對象囱嫩。散點圖打破了這種趨勢恃疯,它們使用點幾何對象。如上面的兩幅圖所示墨闲,我們可以使用不同的幾何對象來表示同樣的數(shù)據(jù)今妄。左側(cè)的圖使用了點幾何對象,右側(cè)的圖使用了平滑曲線幾何對象鸳碧,以一條平滑曲線來擬合數(shù)據(jù)盾鳞。要想改變圖中的幾何對象,需要修改添加在ggplot() 函數(shù)中的幾何對象函數(shù)杆兵。舉例來說雁仲,要想繪制出上圖,你可以使用以下代碼:
# 左圖
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy))
# 右圖
ggplot(data = mpg) +
geom_smooth(mapping = aes(x = displ, y = hwy))
ggplot2 中的每個幾何對象函數(shù)都有一個mapping 參數(shù)琐脏。但是攒砖,不是每種圖形屬性都適合每種幾何對象。你可以設(shè)置點的形狀日裙,但不能設(shè)置線的“形狀”吹艇,而可以設(shè)置線的線型篷帅。geom_smooth() 函數(shù)可以按照不同的線型繪制出不同的曲線洒忧,每條曲線對應映射到線型的變量的一個唯一值:
ggplot(data = mpg) +
geom_smooth(mapping = aes(x = displ, y = hwy, linetype = drv))
根據(jù)表示汽車驅(qū)動系統(tǒng)的drv 變量的值,這里的geom_smooth() 函數(shù)分別用3 條曲線來表示汽車魏颓。一條線表示drv 值為4 的所有汽車格侯,一條線表示drv 值為f 的所有汽車鼻听,另一條線表示drv 值為r 的所有汽車。其中4 表示四輪驅(qū)動联四,f 表示前輪驅(qū)動撑碴,r 表示后輪驅(qū)動。如果你覺得這有些難以理解朝墩,我們可以將這些曲線覆蓋在原始數(shù)據(jù)上醉拓,并按照drv 值對所有的點和線進行著色,這樣你就能看得更清楚一些了。
要想在同一張圖中顯示多個幾何對象亿卤,可以向ggplot() 函數(shù)中添加多個幾何對象函數(shù):
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
geom_smooth(mapping = aes(x = displ, y = hwy))
但是愤兵,這樣代碼就產(chǎn)生了一些重復。假如你想將y 軸上的變量從hwy 改成cty排吴,那么就要在兩個地方修改這個變量秆乳,但你或許會漏掉一處。避免這種重復的方法是將一組映射傳遞給ggplot() 函數(shù)傍念。ggplot2 會將這些映射作為全局映射應用到圖中的每個幾何對象中矫夷。
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth()
如果將映射放在幾何對象函數(shù)中,那么ggplot2 會將其看作這個圖層的局部映射憋槐,它將使用這些映射擴展或覆蓋全局映射双藕,但僅對該圖層有效。這樣一來阳仔,我們就可以在不同的圖層中顯示不同的圖形屬性:
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(color = class)) +
geom_smooth()
同理忧陪,你也可以為不同的圖層指定不同的數(shù)據(jù)。下圖中的平滑曲線表示的只是mpg 數(shù)據(jù)集的一個子集近范,即微型車嘶摊。geom_smooth() 函數(shù)中的局部數(shù)據(jù)參數(shù)覆蓋了ggplot() 函數(shù)中的全局數(shù)據(jù)參數(shù),當然僅對這個圖層有效:
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(color = class)) +
geom_smooth(
data = filter(mpg, class == "subcompact"),
se = FALSE
)
練習
(1) 在繪制折線圖评矩、箱線圖叶堆、直方圖和分區(qū)圖時,應該分別使用哪種幾何對象斥杜?
折線圖使用了直線幾何對象虱颗,箱線圖使用了矩形和直線幾何圖像、直方圖使用了使用了矩形幾何對象
(2) 在腦海中運行以下代碼蔗喂,并預測會有何種輸出忘渔。接著在R 中運行代碼,并檢查你的預測是否正確缰儿。
ggplot(
data = mpg,
mapping = aes(x = displ, y = hwy, color = drv)
) +
geom_point() +
geom_smooth(se = FALSE)
(3) show.legend = FALSE 的作用是什么畦粮?刪除它會發(fā)生什么情況?你覺得我為什么要在本章前面的示例中使用這句代碼乖阵?
sohw.legend=FLASE去掉圖例
(4) geom_smooth() 函數(shù)中的se 參數(shù)的作用是什么宣赔?
se如果設(shè)定為TRUE,則會為曲線設(shè)定置信區(qū)間瞪浸,F(xiàn)LASE則沒有置信區(qū)間
(6) 自己編寫R 代碼來生成以下各圖拉背。
#######1
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth(se=FALSE)
#######2
ggplot() +
geom_point(
data = mpg,
mapping = aes(x = displ, y = hwy)
) +
geom_smooth(
data = mpg,
mapping = aes(x = displ, y = hwy,group=drv),se=FALSE)
#######3
ggplot(data = mpg, mapping = aes(x = displ, y = hwy,color=drv)) +
geom_point() +
geom_smooth(se = FALSE)
#######4
ggplot() +
geom_point(
data = mpg,
mapping = aes(x = displ, y = hwy,color=drv)
) +
geom_smooth(
data = mpg,
mapping = aes(x = displ, y = hwy),se=FALSE)
######5
ggplot() +
geom_point(
data = mpg,
mapping = aes(x = displ, y = hwy,color=drv)
) +
geom_smooth(
data = mpg,
mapping = aes(x = displ, y = hwy,linetype=drv),se=FALSE)
######6
ggplot() +
geom_point(
data = mpg,
mapping = aes(x = displ, y = hwy,color=drv))
1.7 統(tǒng)計變換
接下來我們看一下條形圖。條形圖雖然簡單默终,但很有意思,因為它可以揭示出圖形中的一些微妙信息。我們看一下用geom_bar() 函數(shù)就可以繪制的基本條形圖齐蔽。下面的條形圖顯示了diamonds 數(shù)據(jù)集中按照cut 變量分組的各種鉆石的總數(shù)量两疚。diamonds 數(shù)據(jù)集是ggplot2的內(nèi)置數(shù)據(jù)集,包含大約54 000 顆鉆石的信息含滴,每顆鉆石具有price诱渤、carat、color谈况、clarity 和cut 變量勺美。條形圖顯示,高質(zhì)量切割鉆石的數(shù)量要比低質(zhì)量切割鉆石的數(shù)量多:
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut))
條形圖x 軸顯示的是cut碑韵,這是diamonds 數(shù)據(jù)集中的一個變量赡茸。y 軸顯示的是count,但count 不是diamonds 中的變量祝闻!那么count 來自哪里呢占卧?很多圖形繪制的是數(shù)據(jù)集的原始數(shù)據(jù),比如散點圖联喘。另外一些圖形則可以繪制那些計算出的新數(shù)據(jù)华蜒,比如條形圖。
? 條形圖豁遭、直方圖和頻率多邊形圖可以對數(shù)據(jù)進行分箱叭喜,然后繪制出分箱數(shù)量和落在每個分箱的數(shù)據(jù)點的數(shù)量。
? 平滑曲線會為數(shù)據(jù)擬合一個模型蓖谢,然后繪制出模型預測值捂蕴。
? 箱線圖可以計算出數(shù)據(jù)分布的多種摘要統(tǒng)計量,并顯示一個特殊形式的箱體蜈抓。
繪圖時用來計算新數(shù)據(jù)的算法稱為stat(statistical transformation启绰,統(tǒng)計變換)。下圖描述了geom_bar() 函數(shù)的統(tǒng)計變換過程沟使。
通常來說委可,幾何對象函數(shù)和統(tǒng)計變換函數(shù)可以互換使用。例如腊嗡,你可以使用stat_count()替換geom_bar() 來重新生成前面那張圖:
ggplot(data = diamonds) +
stat_count(mapping = aes(x = cut))
你可能想要覆蓋從統(tǒng)計變換生成的變量到圖形屬性的默認映射着倾。例如,你或許想顯示一張表示比例(而不是計數(shù))的條形圖:
ggplot(data = diamonds) +
geom_bar(
mapping = aes(x = cut, y = ..prop.., group = 1)
)
你可能想要在代碼中強調(diào)統(tǒng)計變換燕少。例如卡者,你可以使用stat_summary() 函數(shù)將人們的注意力吸引到你計算出的那些摘要統(tǒng)計量上。stat_summary() 函數(shù)為x 的每個唯一值計算y 值的摘要統(tǒng)計:
練習
(1) stat_summary() 函數(shù)的默認幾何對象是什么客们?不使用統(tǒng)計變換函數(shù)的話崇决,如何使用幾何對象函數(shù)重新生成以上的圖材诽?
geom_pointrange,
(2) geom_col() 函數(shù)的功能是什么恒傻?它和geom_bar() 函數(shù)有何不同脸侥?
直方圖,其中柱狀圖的高度表示數(shù)據(jù)中的值盈厘,geom_col()的默認統(tǒng)計變換為identity()睁枕,geom_bar()默認為count()
1.8 位置調(diào)整
可以使用color 或者fill(這個更有用)圖形屬性來為條形圖上色:
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, color = cut))
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = cut))
如果將fill 圖形屬性映射到另一個變量(如clarity),那么條形會自動分塊堆疊起來沸手。每個彩色矩形表示cut 和clarity 的一種組合外遇。
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = clarity))
這種堆疊是由position 參數(shù)設(shè)定的位置調(diào)整功能自動完成的。如果不想生成堆疊式條形圖契吉,你還可以使用以下3 種選項之一:"identity"跳仿、"fill" 和"dodge"。
? position = "identity" 將每個對象直接顯示在圖中栅隐。這種方式不太適合條形圖塔嬉,因為條形會彼此重疊。為了讓重疊部分能夠顯示出來租悄,我們可以設(shè)置alpha 參數(shù)為一個較小的數(shù)谨究,從而使得條形略微透明;或者設(shè)定fill = NA泣棋,讓條形完全透明:
ggplot(
data = diamonds,
mapping = aes(x = cut, fill = clarity)
) +
geom_bar(alpha = 1/5, position = "identity")
ggplot(
data = diamonds,
mapping = aes(x = cut, color = clarity)
) +
geom_bar(fill = NA, position = "identity")
? position = "fill" 的效果與堆疊相似胶哲,但每組堆疊條形具有同樣的高度,因此這種條形圖可以非常輕松地比較各組間的比例:
ggplot(data = diamonds) +
geom_bar(
mapping = aes(x = cut, fill = clarity),
position = "fill"
)
? position = "dodge" 將每組中的條形依次并列放置潭辈,這樣可以非常輕松地比較每個條形表示的具體數(shù)值:
ggplot(data = diamonds) +
geom_bar(
mapping = aes(x = cut, fill = clarity),
position = "dodge"
)
回憶一下我們的第一張散點圖鸯屿。你是否發(fā)現(xiàn),雖然數(shù)據(jù)集中有234 個觀測值把敢,但散點圖中只顯示了126 個點寄摆?
因為hwy 和displ 的值都進行了舍入取整,所以這些點顯示在一個網(wǎng)格上時修赞,很多點彼此重疊了婶恼。這個問題稱為過繪制。點的這種排列方式很難看出數(shù)據(jù)的聚集模式柏副。數(shù)據(jù)點是均勻地分布在圖中勾邦,還是存在hwy 和displ 的特殊組合,其中包括了109 個點割择?
通過將位置調(diào)整方式設(shè)為“抖動”眷篇,可以避免這種網(wǎng)格化排列。position = "jitter" 為每個數(shù)據(jù)點添加一個很小的隨機擾動荔泳,這樣就可以將重疊的點分散開來蕉饼,因為不可能有兩個點會收到同樣的隨機擾動:
添加隨機性來改善圖形似乎是一種奇怪的方式虐杯,然而盡管這種方式會損失圖形的精確性,但可以大大提高圖形的啟發(fā)性椎椰。因為這種操作的用處非常大厦幅,所以ggplot2 提供了geom_point(position = "jitter") 的一種快速實現(xiàn)方式:geom_jitter()。
1.9坐標系
坐標系可能是ggplot2 中最復雜的部分慨飘。默認的坐標系是笛卡兒直角坐標系,可以通過其獨立作用的x 坐標和y 坐標找到每個數(shù)據(jù)點译荞。偶爾也會用到一些其他類型的坐標系瓤的。
? coord_flip() 函數(shù)可以交換x 軸和y 軸。當想要繪制水平箱線圖時吞歼,這非常有用圈膏。它也非常適合使用長標簽,但要想在x 軸上不重疊地安排好它們是非常困難的:
ggplot(data = mpg, mapping = aes(x = class, y = hwy)) +
geom_boxplot()
ggplot(data = mpg, mapping = aes(x = class, y = hwy)) +
geom_boxplot() +
coord_flip()
? coord_polar() 函數(shù)使用極坐標系篙骡。極坐標系可以揭示出條形圖和雞冠花圖間的一種有趣聯(lián)系:
bar <- ggplot(data = diamonds) +
geom_bar(
mapping = aes(x = cut, fill = cut),
show.legend = FALSE,
width = 1
) +
theme(aspect.ratio = 1) +
labs(x = NULL, y = NULL)
p1<-bar + coord_flip()
p2<-bar + coord_polar()
ggarrange(p1, p2)
1.10 圖形分層語法
在前面幾節(jié)中稽坤,你學到的絕不僅僅是如何繪制散點圖、條形圖和箱線圖糯俗,而是使用ggplot2繪制任何類型圖形的基礎(chǔ)知識尿褪。為了說明這一點,我們向前面的代碼模板中添加位置調(diào)整得湘、統(tǒng)計變換杖玲、坐標系和分面:
ggplot(data = <DATA>) +
<GEOM_FUNCTION>(
mapping = aes(<MAPPINGS>),
stat = <STAT>,
position = <POSITION>
) +
<COORDINATE_FUNCTION> +
<FACET_FUNCTION>
為了說明圖形語法的工作方式,我們看一下如何從頭開始構(gòu)建一個基本圖形:首先需要有一個數(shù)據(jù)集淘正,然后(通過統(tǒng)計變換)將其轉(zhuǎn)換為想要顯示的信息摆马。
接下來,你可以選擇一個幾何對象來表示轉(zhuǎn)換后的數(shù)據(jù)中的每個觀測值鸿吆,然后選擇幾何對象的圖形屬性來表示數(shù)據(jù)中的變量囤采,這會將每個變量的值映射為圖形屬性的水平。
下一步是選擇放置幾何對象的坐標系惩淳。你可以使用對象位置(對象本身的一個圖形屬性)來顯示x 變量和y 變量的值蕉毯。這樣就生成了一張完整的圖。但你還可以進一步調(diào)整幾何對象在坐標系中的位置(位置調(diào)整)黎泣,或者將圖劃分為多個子圖(分面)恕刘。你還可以通過添加一個或多個附加圖層對圖進行擴展,其中每個附加圖層都使用一個數(shù)據(jù)集抒倚、一個幾何對象褐着、一個映射集合、一個統(tǒng)計變換和一個位置調(diào)整托呕。