關卡 1
各位同學好,本次課程的目標是介紹ggplot2套件。
關卡 2
為什麼我們在學過看過R的繪圖功能後,還要學ggplot2呢? 因為以下幾個理由:ggplot2提供更美觀的預設圖片。所以我們不用作大量的微調,就可以獲得不錯的圖。 我們也可以利用theme的功能,直接取用其他貢獻者繪製的樣本,畫出不同風格的圖。
關卡 3
圖形本身會完整的物件化。而且使用者可以對物件化的圖形進行修正。 也就是說,你可以把繪圖的指令結果,存到變數之中。 而在存到變數中之後還可以操作這個變數,更改我們想要的繪圖效果。
關卡 4
ggplot2和data.frame整合得更好,所以將資料整理成結構化資料後,ggplot2更能發揮威力。
關卡 5
更完整的文件如下。 <http://docs.ggplot2.org>裡面收錄了所有的繪圖指令。
關卡 6
如果同學能在前面的章節學到繪圖的要領,那ggplot2就可以讓同學在實務上更順的串接「資料收集」、「資料整理」與「資料視覺化」的步驟了。
關卡 7
請同學先安裝ggplot2。
check_then_install("ggplot2", "2.0.0")
關卡 8
請同學載入ggplot2。
library(ggplot2)
關卡 9
由於ggplot2沒有提供上手的vignette,我們就略過查詢vignette的動作。 但是還是要提醒同學,當學習一個新套件時,第一個步驟不外乎就是先從讀README、找vignette開始。
關卡 10
我們還是先從infert
這筆數據開始。 請同學輸入:g <- ggplot(infert, aes(x = education))
建立一個ggplot2物件。
g <- ggplot(infert, aes(x = education))
關卡 11
ggplot
函數通常只需要一個參數。 第一個參數是一個data.frame,負責提供資料。 而後續的參數則會通通被傳遞給後續用+
連結的繪圖函數。
關卡 12
請同學輸入:g + geom_bar()
,繪製第一個ggplot2的長條圖。請同學試試看。
g + geom_bar()
關卡 13
geom_bar
會繪製出一個圖層,裡面的內容就是依據infert
所繪製的bar chart(長條圖)。 為了更仔細的解釋,先請同學輸入:?geom_bar
打開這個函數的說明文件。
?geom_bar
關卡 14
ggplot2的說明文件和一般的函數較為不同,舉geom_bar
為例。 geom_bar
的參數有:mapping
, data
, stat
和position
。 mapping
與data
幾乎是所有geom_
開頭的函數都會具備的,所以大家理解一次就夠了。 一般來說,我們不會在geom_
開頭的函數指定data
參數。 在這個例子,因為我們輸入的是:g + geom_bar()
,所以geom_bar
就直接透過g
知道它正在依照infert
繪圖。
關卡 15
infert
的資料欄位這麼多,ggplot怎麼知道畫的是education呢?就是透過geom_bar
的mapping
參數。 當初我們在建立g
的指令是:ggplot(infert, aes(x = education))
。 這裡的第二個參數,會被傳遞到geom_bar
的mapping
參數。 而mapping
的參數,都是用aes
建立的對應物件,語法就類似:aes(x = education)
一樣。 (請注意,education不需要加上雙引號)。
關卡 16
那aes
裡面需要哪些參數呢? 每個geom_
開頭的函數需要的mapping
不太一樣。 請同學直接看說明文件中Aesthetics
的段落。 ggplot2列出了所有需要的欄位,而黑色粗體字的是必須要填入的(如:x
)。 其他的選項有預設值,所以我們不需要給。 而這些mapping
是代表什麼意思呢?
關卡 17
所有mapping
裡面的東西,都會被視為data
的欄位名稱。 舉例來說,請同學輸入:g + geom_bar(aes(fill = education))
。
g + geom_bar(aes(fill = education))
關卡 18
同學有沒有注意到,長條圖中區域的顏色改變了。 fill
在這裡就代表填滿區塊的顏色。 ggplot2在收到fill = education
之後,就會去尋找infert的education欄位。 如果找不到,就會找外部名稱為education的變數。 找到以後,ggplot2就會依照預設的調色盤,根據education的值予以配色,每一個類別擁有一個顏色。 同時也在右半邊新增顏色與education類別對應的說明。
關卡 19
這次請同學輸入:g + geom_bar(aes(fill = "purple"))
。
g + geom_bar(aes(fill = "purple"))
關卡 20
但是儘管我們輸入“purple”,ggplot2還是用粉紅色來呈現,而不是紫色。 這是因為有加雙引號,所以ggplot2在收到“purple”之後,就會假設infert中有一個欄位,其中所有的值都是“purple”。 而ggplot2有內建的調色盤,所以就運用調色盤中第一個顏色來著色。 在ggplot2中,如果要指定顏色,只有設定調色盤的顏色一途,無法單純透過ggplot
或geom_bar
來達成。 這點和R 基礎的繪圖API是不同的。
關卡 21
所有mapping
參數,也就是aes
中的設定,ggplot都是依照同樣的思維來處理:都是對應到data
的欄位。
關卡 22
接著我們使用前面課程用過的hsb
資料集做範例。 請同學輸入:g <- ggplot(hsb)
。
g <- ggplot(hsb)
關卡 23
在我們沒有指定圖層的時候,R是不會畫出圖的,所以上一個指令沒有畫出新的圖。 接著請同學輸入:g + geom_bar(aes(x = sex))
畫出「呈現性別分佈」的長條圖。
g + geom_bar(aes(x = sex))
關卡 24
同學應該會看到「呈現性別分佈」的長條圖。 請同學這次輸入:g + geom_bar(aes(x = sex, fill = race))
。
g + geom_bar(aes(x = sex, fill = race))
關卡 25
由於x = sex
,所以長條圖是以sex
為主。 且因為fill = race
,所以顏色是以種族為主。 接著請同學輸入:g + geom_bar(aes(x = sex, fill = race), position = "dodge")
。
g + geom_bar(aes(x = sex, fill = race), position = "dodge")
關卡 26
請比較用g + geom_bar(aes(x = sex,fill=race))
與g + geom_bar(aes(x = sex, fill = race), position = "dodge")
的差異。 當position = "stack"
(預設值)時,長條圖型會將race推疊呈現,而此時圖的重點是在於比較sex個數的差異。 而當position = "dodge"
時,長條圖會將race錯開呈現,而此時圖的重點是在於比較相同sex中,不同race個數的差異。
關卡 27
接著請同學輸入skip()
檢查有無安裝dplyr。
check_then_install("dplyr", "0.4.3")
關卡 28
請同學載入dplyr。
library(dplyr)
關卡 29
請同學利用group_by
和summarise
計算不同sex類別的個數。
# 請計算sex類別的個數
answer01 <- local({
# 請在這邊填寫你的程式碼
group_by(hsb, sex) %>%
summarise(count = n())
})
# 請先確定你的答案通過以下測試
stopifnot(colnames(answer01) == c("sex", "count"))
stopifnot(nrow(answer01) == 2)
stopifnot(is.data.frame(answer01))
stopifnot(sum(answer01$count) == nrow(hsb))
stopifnot(sort(answer01$sex) == sort(c("female", "male")))
# 確認完畢之後,請回到console輸入`submit()`
關卡 30
請同學輸入:ggplot(answer01, aes(x = sex)) + geom_bar()
。
ggplot(answer01, aes(x = sex)) + geom_bar()
關卡 31
我們會看到一張長條圖,表示兩種性別都是1。 會有這樣的結果,是因為在answer01
中,兩種性別各佔一筆資料。 為了要讓長條圖理解值位於count
的欄位,我們必須要改成輸入:ggplot(answer01, aes(x = sex, y = count)) + geom_bar(stat = "identity")
。
ggplot(answer01, aes(x = sex, y = count)) + geom_bar(stat = "identity")
關卡 32
在剛剛的例子中,stat = "identity"
的意思,就是在告訴ggplot直接取用count
欄位當成高度即可,不用再數資料的個數了。
關卡 33
geom_bar
的stat
和position
是和長條圖相關的參數。 在aes
中的參數,如同x
、y
和fill
,即使是x-y散佈圖或boxplot,都會使用到的參數。 而ggplot2的設計就是把能共通使用的繪圖參數放到aes
中,個別圖種自己使用的參數,則放在geom_
開頭的函數中。
關卡 34
接著請同學輸入:ggplot(hsb, aes(x = math)) + geom_density()
。
ggplot(hsb, aes(x = math)) + geom_density()
關卡 35
上一張圖畫出了math
欄位的分佈圖。 接著我們可以依據性別,畫出不同性別的分佈圖。 請同學輸入:ggplot(hsb, aes(x = math, color = sex)) + geom_density()
。
ggplot(hsb, aes(x = math, color = sex)) + geom_density()
關卡 36
請同學依據race
,繪製出不同種族的read
欄位成績分佈。(請修改上一題的答案)
ggplot(hsb, aes(x = read, color = race)) + geom_density()
關卡 37
請同學先輸入?geom_density
打開說明。
?geom_density
關卡 38
請問以下哪一個是geom_density
特有的參數?
stat
關卡 39
接下來我們來比較不同性別在公立、私立學校的數學表現。 請同學先輸入以下程式碼:dat2 <- summarise(group_by(hsb, sex, schtyp), math.avg = mean(math))
。
dat2 <- summarise(group_by(hsb, sex, schtyp), math.avg = mean(math))
關卡 40
接著,我們輸入:g <- ggplot(dat2, aes(x = sex, y = math.avg, fill = schtyp))
建立一個基於dat2的ggplot物件。
g <- ggplot(dat2, aes(x = sex, y = math.avg, fill = schtyp))
關卡 41
請同學先回憶我們對geom_bar
的參數stat
的解說。 請問同學,如果我們輸入:g + geom_bar(stat = <??>)
,stat
的參數要給多少呢?
identity
關卡 42
請輸入:g2 <- g + geom_bar(stat = "identity", position = "dodge")
。
g2 <- g + geom_bar(stat = "identity", position = "dodge")
關卡 43
請同學輸入g2
看一下繪圖結果。
g2
關卡 44
ggplot 依照性別與公立私立,分別呈現了數學平均。 更貼心的是,圖例也已經自動產生了。 如果我們想要調整y軸的範圍,放大視覺化的差異呢? 請同學輸入:g2 + coord_cartesian(ylim=c(40,60))
。
g2 + coord_cartesian(ylim=c(40,60))
關卡 45
同學除了可以學習coord_cartesian
這個語法之外,也請注意到我們可以把畫圖的指令當成變數給存到如g2
的R物件之中。 之後若我們要做調整(例如調整y軸的範圍)只要從g2
開始用+
下指令即可。 這樣的設計讓我們在調整圖形上更方便。
關卡 46
在上一堂課程中,我們有介紹過dotchart。 ggplot2中也有提供類似的圖層: geom_point。 請同學輸入:g3 <- g + geom_point(aes(color = schtyp), size = 10)
。
g3 <- g + geom_point(aes(color = schtyp), size = 10)
關卡 47
請輸入g3
,看看繪圖結果。
g3
關卡 48
如果要改成水平方向,可以使用:g3 + coord_flip()
。
g3 + coord_flip()
關卡 49
ggplot2把這些跟座標軸的縮放、翻轉的功能都放到coord
開頭的函數了。 繪圖常用的座標轉換,像是取log,也都有對應的函數,並且都是以coord_
開頭。 就如同繪圖、製作圖層的函數都是geom_
開頭一樣。 這些API的設計比起R 的繪圖API是更有系統了。
關卡 50
除了觀察單一統計量之外,ggplot2也支援統計學常用的boxplot。 請同學輸入:g <- ggplot(hsb, aes(x = sex, y = math, fill = schtyp))
,先告訴ggplot2要如何進行數據分組。
g <- ggplot(hsb, aes(x = sex, y = math, fill = schtyp))
關卡 51
接著,我們可以使用geom_boxplot產生圖層:g + geom_boxplot()
。
g + geom_boxplot()
關卡 52
需要的話,我們可以增加更多欄位,讓boxplot有更多的變化。 舉例來說,我們可以加上linetype: g + geom_boxplot(aes(linetype = race))
。
g + geom_boxplot(aes(linetype = race))
關卡 53
雖然這張圖有點複雜,但是因為ggplot2會自動生成圖例,所以仔細觀察後仍可以很清楚地看到各群分組的差異。 舉例來說,圖中顯示某族裔美國人的女學生,在公立與私立學校的數學表現差異很大。 請問同學,這是哪一個種族呢?A: African American, B: Asian, C: Hispanic, D: White
C
關卡 54
接下來我們試試看畫散佈圖。請同學輸入:g <- ggplot(hsb, aes(x = math, y = read))
。
g <- ggplot(hsb, aes(x = math, y = read))
關卡 55
輸入g + geom_point()
讓ggplot以散佈圖的方式繪製圖層。
g + geom_point()
關卡 56
還記得上一個課程最後所繪製的一張圖:一口氣運用點的大小、形狀、顏色來表示science的表現、公立私立與學生的性別。 我們也可以在ggplot2中做到:g + geom_point(aes(size = science, pch = schtyp, color = sex))
。
g + geom_point(aes(size = science, pch = schtyp, color = sex))
關卡 57
而且ggplot也自動加上圖標了!
關卡 58
接著我們介紹如何調整ggplot2的配色。 假設各位同學想要使用對色盲友善的配色系列,在參考Wong. B (2011) Points of View: Color blindness. Nature Methods 8:411後, 請同學輸入以下的指令:cb7 <- c("#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
。
cb7 <- c("#000000", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
關卡 59
接著我們先繪製沒修正配色之前的版本。 請同學輸入:g <- ggplot(hsb, aes(x = sex, fill = race)) + geom_bar()
。
g <- ggplot(hsb, aes(x = sex, fill = race)) + geom_bar()
關卡 60
我們讓R畫出沒修正的版本。請輸入g
。
g
關卡 61
接著我們輸入:g + scale_fill_manual(values=cb7)
來修改配色。
g + scale_fill_manual(values=cb7)
關卡 62
在ggplot2的世界裡,所有圖形的調整,都是透過+
連接特定的函數來完成的。
關卡 63
接下來我們介紹一個函數:ggtheme
。 它讓我們可以輕鬆的轉換ggplot的繪圖風格。 請同學試試看:g + theme_minimal()
。
g + theme_minimal()
關卡 64
同學可以輸入?ggtheme
來查詢所有可用的theme。
關卡 65
也可以使用ggsave
來將圖片輸出到檔案中。 請同學先輸入:dst <- tempfile(fileext = ".png")
隨機生成一個暫存檔路徑。
dst <- tempfile(fileext = ".png")
關卡 66
請同學輸入:ggsave(dst)
來將目前的ggplot2圖輸出到dst
路徑。
ggsave(dst)
關卡 67
接著請同學輸入:g <- ggplot(hsb, aes(x = read, y = math)) + geom_point()
。 這裡g
就代表read v.s. math的x-y散佈圖。
g <- ggplot(hsb, aes(x = read, y = math)) + geom_point()
關卡 68
我們如果想要一個race
的類別畫一張圖呢? 請同學輸入:g + facet_grid(. ~ race)
。
g + facet_grid(. ~ race)
關卡 69
剛剛的face_grid
是一個比較進階的函數。 同學只要記得,如果要對某一個欄位做展開,例如剛剛的動作就是對race
做展開,每個race
畫一張圖, 第一個參數的formula中,~
的左邊放.
,右邊放要展開的欄位名稱即可(不需要加引號)。
關卡 70
如果我們要一次畫出多筆數據兩兩間的散佈圖,就需要使用GGally這個套件。 請同學安裝。
check_then_install("GGally", "1.0.1")
關卡 71
請載入GGally套件。
library(GGally)
關卡 72
如果我們想要看read, write, math, science 兩兩組合的x-y散佈圖,我們只要輸入:ggpairs(hsb, 7:10)
。 註: 這些欄位分別位於hsb的第7至第10欄。
ggpairs(hsb, 7:10)
關卡 73
我們這堂課對ggplot2的介紹就到這裡了。接下來就是挑戰時間。
關卡 74
我們自內政部資料開放平台下載了個村(里)戶籍人口統計月報表。 有興趣的同學可以輸入:population_src()
來瀏覽資料來源。 這裡請同學輸入:head(population)看一下這筆資料。
head(population)
關卡 75
接下來我們會在每個步驟先畫一張圖給同學參考。 請同學依照指示從population
中畫出類似的圖。 受限於技術,目前我們只能請同學自行比對答案。 完成之後請同學輸入submit()
後就可以進行下一個挑戰。 請同學輸入skip()
開始第一個挑戰。
begin_rvisualization_03()
關卡 76
請同學想辦法從population
資料中畫出與參考圖一樣的圖。 如果想要再看一次參考圖,請輸入:hw_01()
。 如果想要直接看參考答案,請輸入:hw_01
。
關卡 77
請同學想辦法從population
資料中,畫出自己居住地的村(里)與性別的分佈圖。 具體細節請見參考圖。 如果想要再看一次參考圖,請輸入:hw_02()
。 如果想要直接看參考答案,請輸入:hw_02
。
關卡 78
請同學想辦法從population
資料中畫出自己居住地的性別與年齡的分佈圖。 x軸是年齡、y軸是該年齡的人數,不同的顏色則代表不同性別的資料。 具體細節請見參考圖。 如果想要再看一次參考圖,請輸入:hw_03()
。 如果想要直接看參考答案,請輸入:hw_03
。
關卡 79
請同學想辦法從population
資料中畫出自己居住地的性別與年齡的分佈圖。 x軸是年齡、y軸是該年齡的比率,不同的顏色則代表不同性別的資料。 具體細節請見參考圖。 如果想要再看一次參考圖,請輸入:hw_04()
。 如果想要直接看參考答案,請輸入:hw_04
。