輕鬆學習 R 語言：視覺化的文法
By: Yao-Jen Kuo
Tags: Visualization, Programming, Ggplot2, Data Science, R

The simple graph has brought more information to the data analyst’s mind than any other device. John Tukey

在輕鬆學習 R 語言：基礎探索資料分析我們討論了如何透過 R 語言的內建繪圖系統：Base Plotting System 暸解資料的外觀、維度、變數分佈與相關等探索資料分析（Exploratory Data Analysis，EDA）的要素。除了內建繪圖系統以外，有極高比例的 R 語言使用者其實更依賴使用 ggplot2 這個套件，它以簡潔、彈性和美觀輸出快速擄獲資料科學團隊的芳心；命名之中 gg 指的是 grammer of graphics，套件作者是 Hadley Wickham 與 Winston Chang，核心理念是利用正規而有結構的文法來探索資料。

安裝與載入 ggplot2 套件

我們可以選擇透過命令列（Console）以 install.packages() 函數進行安裝。



## > install.packages("ggplot2")

## trying URL '

## Content type 'application/x-gzip' length 3622365 bytes (3.5 MB)

## ==================================================

## downloaded 3.5 MB

##

##

## The downloaded binary packages are in

## /var/folders/0b/r__z5mpn6ldgb_w2j7_y_ntr0000gn/T//Rtmpw3pDJx/downloaded_packages ## > # 安裝 ggplot2## > install.packages("ggplot2")## trying URL ' https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.5/ggplot2_3.1.0.tgz' ## Content type 'application/x-gzip' length 3622365 bytes (3.5 MB)## ==================================================## downloaded 3.5 MB###### The downloaded binary packages are in## /var/folders/0b/r__z5mpn6ldgb_w2j7_y_ntr0000gn/T//Rtmpw3pDJx/downloaded_packages

或是透過圖形化介面（Graphic User Interface, GUI）的方法安裝，在右下角的 packages 頁籤點選 install，再輸入套件名稱 ggplot2 點選安裝。

透過圖形化介面安裝

我們可以選擇透過命令列（Console）以 library() 函數將套件載入環境來使用。

## > # 載入 ggplot2

## > library(ggplot2)

或是透過圖形化介面（Graphic User Interface, GUI）在右下角的 packages 頁籤下搜尋 ggplot2 然後將前面的核取方框打勾。

透過圖形化介面載入

探索數值分佈

成功安裝且載入 ggplot2 套件後，我們利用探索數值分佈的直方圖暸解所謂的視覺化文法，與輕鬆學習 R 語言：基礎探索資料分析同樣使用 R 語言的套件 gapminder 來載入一個簡易版 gapminder 資料作為多個視覺化圖形的示範資料。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 繪製 gapminder 資料中人均 GDP（ gdpPercap 變數）之分佈

## > gapminder %>%

## + ggplot(aes(x = gdpPercap)) +

## + geom_histogram(bins = 30)

探索 gdpPercap 變數的分佈

這段程式會建立出一個 ggplot 物件並綁定 gapminder 的 gdpPercap 變數到這個物件之上，這裡可以觀察到 ggplot2 套件的繪圖來源是資料框，素材則是資料框中的變數， aes() 負責將素材綁定至 X 軸與 Y 軸，這是 aesthetic mappings 的縮寫；接著我們還要告訴 ggplot 物件要用什麼樣的外觀呈現，這時接著利用 geom_() 指定繪圖的類型，這是 geometric objects 的縮寫，底線後面加上繪圖名稱，以現在繪製的直方圖而言，就要使用 geom_histogram() 加上直方圖外觀。在 ggplot 物件上疊加 geometric objects 的運算子是加號 + ，未來如果希望在圖形中添加其他自訂元件，都需要利用加號來連結這些函數呼叫。

直方圖的分箱數（bins）使用分箱數 30 這個預設值，可以透過調整 binwidth 或 bins 參數來更改，增加 binwidth 與減少 bins 會減少分箱數；減少 binwidth 與增加 bins 則會增加分箱數。

在繼續檢視不同外觀的資料視覺化之前，我們先以清單羅列這些 geom_() 藉此獲得清晰的概觀。

geom_histogram() ：直方圖

：直方圖 geom_boxplot() ：盒鬚圖

：盒鬚圖 geom_line() ：線圖

：線圖 geom_point() ：散佈圖

：散佈圖 stat_function(fun, geom = "line") ：曲線圖

：曲線圖 geom_bar() ：長條圖

探索不同類別與數值分佈的關係

使用 geom_boxplot() 函數繪製盒鬚圖來探索不同類別與數值分佈的關係，以探索 gapminder 資料中不同洲別（ continent 變數）的人均 GDP（ gdpPercap 變數）分布差異為例。

> # 安裝 ggplot2, gapminder, magrittr

> # install.packages(c("ggplot2", "gapminder", "magrittr"))

> # 載入 ggplot2, gapminder, magrittr

> library(ggplot2)

> library(gapminder)

> library(magrittr)

>

> # 探索不同洲別的人均 GDP 分布差異

> gapminder %>%

+ ggplot(aes(x = continent, y = gdpPercap)) +

+ geom_boxplot()

探索不同洲別的人均 GDP 分布差異

探索數值與日期（時間）的關係

使用 geom_line() 函數繪製線圖來探索數值與日期（日期時間）的變化趨勢，以探索 gapminder 資料中台灣的人均 GDP（ gdpPercap 變數）與年份（ year 變數）之變化趨勢為例。

## > # 安裝 ggplot2, gapminder, dplyr

## > # install.packages(c("ggplot2", "gapminder", "dplyr"))

## > # 載入 ggplot2, gapminder, dplyr

## > library(ggplot2)

## > library(gapminder)

## > library(dplyr)

##

## Attaching package: ‘dplyr’

##

## The following objects are masked from ‘package:stats’:

##

## filter, lag

##

## The following objects are masked from ‘package:base’:

##

## intersect, setdiff, setequal, union

##

## >

## > # 探索台灣的人均 GDP 與年份之變化趨勢

## > gapminder %>%

## + filter(country == "Taiwan") %>%

## + ggplot(aes(x = year, y = gdpPercap)) +

## + geom_line()

探索人均 GDP 與年份之變化趨勢

探索兩個數值相關的關係

使用 geom_point() 函數繪製散佈圖來探索兩個數值相關的關係，以探索 gapminder 資料中人均 GDP（ gdpPercap 變數）與預期壽命（ lifeExp 變數）之相關為例。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 探索人均 GDP 與預期壽命之相關

## > gapminder %>%

## + ggplot(aes(x = gdpPercap, y = lifeExp)) +

## + geom_point()

探索人均 GDP 與預期壽命之相關

探索類別的頻率

使用 geom_barplot() 函數繪製長條圖來探索類別的頻率，以探索 gapminder 資料中 1704 個觀測值中各大洲的資料筆數為例。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 探索各大洲的資料筆數

## > gapminder %>%

## + ggplot(aes(x = continent)) +

## + geom_bar()

探索 1704 個觀測值中各大洲的資料筆數

繪畫函數

使用 stat_function(fun, geom = "line") 能夠將內建或者自訂的函數外觀繪製出來，但由於函數輸入的值域很廣（可能為負無限大至正無限大），我們需要在資料框中設定輸入的值域，舉例來說可以將 sin() 函數在 -pi 與 pi 之間描繪出來。

## > # 安裝 ggplot2

## > # install.packages("ggplot2")

## > # 載入 ggplot2

## > library(ggplot2)

## >

## > sin_df <- data.frame(x = c(-pi, pi))

## > ggplot(sin_df, aes(x = x)) + stat_function(fun = sin, geom = "line")

描繪 sin() 函數在 -pi 與 pi 之間的外觀

如果是自訂函數 squared() : f(x) = x² 亦可以用 stat_function(fun, geom = "line") 函數將它在 -3 與 3 之間描繪出來。

## > # 安裝 ggplot2

## > # install.packages("ggplot2")

## > # 載入 ggplot2

## > library(ggplot2)

## >

## > squared <- function(x) {

## + return(x**2)

## + }

## >

## > sqr_df <- data.frame(x = c(-3, 3))

## > ggplot(sqr_df, aes(x = x)) + stat_function(fun = squared, geom = "line")

描繪 squared() 函數在 -3 與 3 之間的外觀

ggplot2 常用的自訂元件

我們已經快速地瀏覽過使用 ggplot2 套件繪畫的基礎圖形，有時候可能基於美觀或解釋性，需要在作圖時加入一些自訂元件，ggplot2 圖形常見會調整的部分像是：

自訂標題、X 軸標籤與 Y 軸標籤

隱藏格線

調整圖形為水平方向

在直方圖上加上密度曲線

調整資料點的形狀與顏色

繪畫多個圖形

疊加 ggtitle() 、 xlab() 與 ylab() 這三個函數就能夠分別指定圖形的標題、X 軸標籤與 Y 軸標籤，其中 lab 是 label 的縮寫。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 在直方圖加上標題與標籤

## > gapminder %>%

## + ggplot(aes(x = gdpPercap)) +

## + geom_histogram(bins = 30) +

## + ggtitle("GDP Per Capita is left-skewed") +

## + xlab("GDP Per Capita") +

## + ylab("Freq")

在直方圖加上標題與軸標籤

ggplot2 繪製的圖形預設都有格線，我們可以疊加 theme() 函數進行非常細緻的格線隱藏設定。

隱藏主要格線： panel.grid.major = element_blank()

隱藏次要格線： panel.grid.minor = element_blank()

隱藏 X 軸主要格線： panel.grid.major.x = element_blank()

隱藏 Y 軸主要格線： panel.grid.major.y = element_blank()

隱藏 X 軸次要格線： panel.grid.minor.x = element_blank()

隱藏 Y 軸次要格線： panel.grid.minor.y = element_blank()

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 隱藏主要與次要格線

## > gapminder %>%

## + ggplot(aes(x = gdpPercap)) +

## + geom_histogram(bins = 30) +

## + theme(panel.grid.major = element_blank(),

## + panel.grid.minor = element_blank())

隱藏主要與次要格線

疊加 coord_flip() 函數調整圖形為水平方向，這是 coordinate flip 的縮寫。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 調整圖形為水平方向

## > gapminder %>%

## + ggplot(aes(x = continent)) +

## + geom_bar() +

## + coord_flip()

調整圖形為水平方向

在 geom_histogram() 中加入 aes(y = ..density..) 以及疊加 geom_density() 可以在直方圖上加上密度曲線。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 在直方圖上加上密度曲線

## > gapminder %>%

## + ggplot(aes(x = gdpPercap)) +

## + geom_histogram(bins = 30, aes(y = ..density..), alpha = 0.5) +

## + geom_density()

在直方圖上加上密度曲線

在 geom_point() 函數中加入 shape 與 colour 的設定調整資料點的形狀與顏色。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 調整資料點為紅色的空心三角形

## > gapminder %>%

## + ggplot(aes(x = gdpPercap, y = lifeExp)) +

## + geom_point(shape = 2, colour = "red")

調整資料點為紅色的空心三角形\

使用不同類別區分資料點的形狀與顏色在 ggplot2 可以很容易辦到，將 shape 與 colour 的對應到指定變數即可。

## > # 安裝 ggplot2, gapminder, magrittr

## > # install.packages(c("ggplot2", "gapminder", "magrittr"))

## > # 載入 ggplot2, gapminder, magrittr

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## >

## > # 以洲別區分資料點形狀顏色

## > gapminder %>%

## + ggplot(aes(x = gdpPercap, y = lifeExp)) +

## + geom_point(aes(shape = continent, colour = continent))

以洲別區分資料點形狀顏色

ggplot2 套件本身並沒有針對繪畫多個圖形這部分設計函數，但我們可以利用另一個套件 gridExtra 所提供的 grid.arrange() 函數來達到像是 Base Plotting System 中 par(mfrow = c(m, n)) 所呈現的效果。

## > # 安裝 ggplot2, gapminder, magrittr, gridExtra

## > # install.packages(c("ggplot2", "gapminder", "magrittr", "gridExtra"))

## > # 載入 ggplot2, gapminder, magrittr, gridExtra

## > library(ggplot2)

## > library(gapminder)

## > library(magrittr)

## > library(gridExtra)

##

## Attaching package: ‘gridExtra’

##

## The following object is masked from ‘package:dplyr’:

##

## combine

##

## >

## > # 垂直的長條圖

## > g1 <- gapminder %>%

## + ggplot(aes(x = continent)) +

## + geom_bar()

## > # 水平的長條圖

## > g2 <- gapminder %>%

## + ggplot(aes(x = continent)) +

## + geom_bar() +

## + coord_flip()

## > # 水平的長條圖無主要格線

## > g3 <- gapminder %>%

## + ggplot(aes(x = continent)) +

## + geom_bar() +

## + coord_flip() +

## + theme(panel.grid.major = element_blank(),

## + panel.grid.minor = element_blank())

## > # 垂直的長條圖無主要格線

## > g4 <- gapminder %>%

## + ggplot(aes(x = continent)) +

## + geom_bar() +

## + theme(panel.grid.major = element_blank(),

## + panel.grid.minor = element_blank())

## > # 繪畫多個圖形於一個畫布上

## > grid.arrange(g1, g2, g3, g4, nrow = 2, ncol = 2)

繪畫多個圖形於一個畫布上

我們雖然已經介紹了一定程度關於 ggplot2 的技巧，但是這些功能都只佔其中非常小的一部分，因為繪圖可以調整的參數與功能實在太豐富了，在有限的章節內容我們只能夠探討探索性分析常用的繪圖需求。實務上在使用繪圖功能時多半會伴隨大量的官方文件查詢、Google 搜尋與 StackOverflow 搜尋，所以如果您在一開始遭遇到很多的困難，這是再正常不過的情形了，請耐住性子，多畫幾次就會漸入佳境的！

小結

在這個小節中我們簡介以 R 語言實踐視覺化的文法 Grammar of Graphics，以 ggplot2 套件作資料視覺化，包含基礎的視覺化圖形與常用的自訂元件。