關卡 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, statpositionmappingdata幾乎是所有geom_開頭的函數都會具備的,所以大家理解一次就夠了。 一般來說,我們不會在geom_開頭的函數指定data參數。 在這個例子,因為我們輸入的是:g + geom_bar(),所以geom_bar就直接透過g知道它正在依照infert繪圖。

關卡 15

infert的資料欄位這麼多,ggplot怎麼知道畫的是education呢?就是透過geom_barmapping參數。 當初我們在建立g的指令是:ggplot(infert, aes(x = education))。 這裡的第二個參數,會被傳遞到geom_barmapping參數。 而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中,如果要指定顏色,只有設定調色盤的顏色一途,無法單純透過ggplotgeom_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_bysummarise計算不同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_barstatposition是和長條圖相關的參數。 在aes中的參數,如同xyfill,即使是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