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