基礎探索資料分析

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

John Tukey

在成功將資料輸入 R 語言開發環境,並成功將載入資料框處理完畢以後之後,下一步要進行的會是探索資料分析(Exploratory Data Analysis,EDA),透過這個步驟可以幫助資料科學團隊暸解資料的外觀、維度以及變數的分佈等資訊,我們可以透過 R 語言的函數與內建繪圖系統:Base Plotting System 來輔助完成探索資料分析的任務。其中常用的內建函數包含像是 nrow()ncol()dim()summary()str()head() 以及 tail()基礎資料框處理章節中已經有了詳盡介紹與範例。

Base Plotting System

這個章節我們要聚焦的是 Base Plotting System,她是 R 語言內建的繪圖系統,提供系列函數各自負責繪製一種圖形,在檢視之前我們先以清單羅列這些函數藉此獲得清晰的概觀。

  • hist() :直方圖
  • boxplot() :盒鬚圖
  • plot(..., type = "l") :線圖
  • plot() :散佈圖
  • curve() :曲線圖
  • barplot() :長條圖

關於示範資料:Gapminder

被 Bill Gates 大力推薦、譽為是他「人生中閱讀過最重要的作品之一,帶領讀者清晰認識世界的指南」,Factfulness 一書是由瑞典 Karolinska 醫學院的國際衛生學教授 Hans Rosling(1948–2017) 所著,Hans Rosling 創辦 Gapminder 基金會,他最著名的 TED Talk: The Best Stats You’ve Ever Seen 被資料科學愛好者奉為視覺化溝通的典範;利用 4 分鐘、使用 1 張互動式圖表、援引超過 12 萬列資料、清晰傳達全世界 200 多個國家、近 200 年的財富及健康演變趨勢。

我們將使用 R 語言的套件 gapminder 來載入一個簡易版 gapminder 資料作為多個視覺化圖形的示範資料。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 觀察有幾個觀測值、幾個變數
dim(gapminder)
# 觀察摘要
summary(gapminder)
# 觀察詳細資訊
str(gapminder)
# 觀察前六個觀測值與後六個觀測值
head(gapminder)
tail(gapminder)
1
2
3
4
5
6
7
8
9
10
11
12
13
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 觀察有幾個觀測值、幾個變數
## > dim(gapminder)
## [1] 1704    6
## > # 觀察摘要
## > summary(gapminder)
##         country        continent        year         lifeExp     
##  Afghanistan:  12   Africa  :624   Min.   :1952   Min.   :23.60  
##  Albania    :  12   Americas:300   1st Qu.:1966   1st Qu.:48.20  
##  Algeria    :  12   Asia    :396   Median :1980   Median :60.71  
##  Angola     :  12   Europe  :360   Mean   :1980   Mean   :59.47  
##  Argentina  :  12   Oceania : 24   3rd Qu.:1993   3rd Qu.:70.85  
##  Australia  :  12                  Max.   :2007   Max.   :82.60  
##  (Other)    :1632                                                
##       pop              gdpPercap       
##  Min.   :6.001e+04   Min.   :   241.2  
##  1st Qu.:2.794e+06   1st Qu.:  1202.1  
##  Median :7.024e+06   Median :  3531.8  
##  Mean   :2.960e+07   Mean   :  7215.3  
##  3rd Qu.:1.959e+07   3rd Qu.:  9325.5  
##  Max.   :1.319e+09   Max.   :113523.1  
##                                        
## > # 觀察詳細資訊
## > str(gapminder)
## Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1704 obs. of  6 variables:
##  $ country  : Factor w/ 142 levels "Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
##  $ continent: Factor w/ 5 levels "Africa","Americas",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ year     : int  1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 ...
##  $ lifeExp  : num  28.8 30.3 32 34 36.1 ...
##  $ pop      : int  8425333 9240934 10267083 11537966 13079460 14880372 12881816 13867957 16317921 22227415 ...
##  $ gdpPercap: num  779 821 853 836 740 ...
## > # 觀察前六個觀測值與後六個觀測值
## > head(gapminder)
## # A tibble: 6 x 6
##   country     continent  year lifeExp      pop gdpPercap
##   <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
## 1 Afghanistan Asia       1952    28.8  8425333      779.
## 2 Afghanistan Asia       1957    30.3  9240934      821.
## 3 Afghanistan Asia       1962    32.0 10267083      853.
## 4 Afghanistan Asia       1967    34.0 11537966      836.
## 5 Afghanistan Asia       1972    36.1 13079460      740.
## 6 Afghanistan Asia       1977    38.4 14880372      786.
## > tail(gapminder)
## # A tibble: 6 x 6
##   country  continent  year lifeExp      pop gdpPercap
##   <fct>    <fct>     <int>   <dbl>    <int>     <dbl>
## 1 Zimbabwe Africa     1982    60.4  7636524      789.
## 2 Zimbabwe Africa     1987    62.4  9216418      706.
## 3 Zimbabwe Africa     1992    60.4 10704340      693.
## 4 Zimbabwe Africa     1997    46.8 11404948      792.
## 5 Zimbabwe Africa     2002    40.0 11926563      672.
## 6 Zimbabwe Africa     2007    43.5 12311143      470.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

探索數值分佈

使用 hist() 函數繪製直方圖來探索數值的分佈,函數命名是 histogram 的縮寫,以探索 gapminder 資料中人均 GDP( gdpPercap 變數)之分佈為例。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索 gdpPercap 變數的分佈
hist(gapminder$gdpPercap)
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索 gdpPercap 變數的分佈
## > hist(gapminder$gdpPercap)
1
2
3
4
5
6

探索 gdpPercap 變數的分佈

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

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

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索不同洲別的人均 GDP 分布差異
boxplot(gdpPercap ~ continent, data = gapminder)
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索不同洲別的人均 GDP 分布差異
## > boxplot(gdpPercap ~ continent, data = gapminder)
1
2
3
4
5
6

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

探索數值與日期(時間)的關係

使用 plot(..., type = "l") 函數繪製線圖來探索數值與日期(日期時間)的變化趨勢,以探索 gapminder 資料中台灣的人均 GDP( gdpPercap 變數)與年份( year 變數)之變化趨勢為例。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索台灣的人均 GDP 與年份之變化趨勢
twn <- gapminder[gapminder$country == "Taiwan", ]
plot(twn$year, twn$gdpPercap, type = "l")
1
2
3
4
5
6
7
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索台灣的人均 GDP 與年份之變化趨勢
## > twn <- gapminder[gapminder$country == "Taiwan", ]
## > plot(twn$year, twn$gdpPercap, type = "l")
1
2
3
4
5
6
7

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

探索兩個數值相關的關係

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

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索人均 GDP 與預期壽命之相關
plot(gapminder$gdpPercap, gapminder$lifeExp)
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索人均 GDP 與預期壽命之相關
## > plot(gapminder$gdpPercap, gapminder$lifeExp)
1
2
3
4
5
6

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

探索類別的頻率

使用 barplot() 函數繪製長條圖來探索類別的頻率,以探索 gapminder 資料中 1704 個觀測值中各大洲的資料筆數為例,這裡可以呼叫 table() 函數,它的作用就像樞紐分析,可以協助我們統整資料。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索各大洲的資料筆數
barplot(table(gapminder$continent))
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索各大洲的資料筆數
## > barplot(table(gapminder$continent))
1
2
3
4
5
6

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

繪畫函數

使用 curve() 函數能夠將內建或者自訂的函數外觀繪製出來,但由於函數輸入的值域很廣(可能為負無限大至正無限大),所以 curve() 函數會有兩個參數 fromto 指定輸入範圍,舉例來說可以將 sin() 函數在 -pipi 之間描繪出來。

curve(sin, from = -pi, to = pi)
1
## > curve(sin, from = -pi, to = pi)
1

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

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

squared <- function(x) {
  return(x**2)
}
curve(squared, from = -3, to = 3)
1
2
3
4
## > squared <- function(x) {
## +     return(x**2)
## + }
## > curve(squared, from = -3, to = 3)
1
2
3
4

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

Base Plotting System 常用的自訂元件

我們已經快速地瀏覽過 Base Plotting System 所提供的基礎系列函數,有時候可能基於美觀或解釋性,需要在作圖時加入一些自訂元件,內建的繪圖系統中常見會調整的部分像是:

  • 自訂標題、X 軸標籤與 Y 軸標籤
  • 加入格線
  • 調整圖形為水平方向
  • 調整刻度顯示方向
  • 調整刻度文字大小
  • 在直方圖上加上密度曲線
  • 調整資料點的形狀與顏色
  • 繪畫多個圖形

在繪圖函數中加入 mainxlabylab 這三個參數就能夠指定圖形的標題、X 軸標籤與 Y 軸標籤,其中 lab 是 label 的縮寫。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 在直方圖加上標題與軸標籤
hist(gapminder$gdpPercap, main = "GDP Per Capita is left-skewed", xlab = "GDP Per Capita", ylab = "Freq")
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 在直方圖加上標題與標籤
## > hist(gapminder$gdpPercap, main = "GDP Per Capita is left-skewed", xlab = "GDP Per Capita", ylab = "Freq")
1
2
3
4
5
6

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

繪圖之後呼叫 grid() 函數能夠為圖形加上 X 軸與 Y 軸的格線。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索人均 GDP 與預期壽命之相關
plot(gapminder$gdpPercap, gapminder$lifeExp, main = "Life Expectancy is positively related to GDP Per Capita", xlab = "GDP Per Capita", ylab = "Life Expectancy")
# 加上格線
grid()
1
2
3
4
5
6
7
8
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索人均 GDP 與預期壽命之相關
## > plot(gapminder$gdpPercap, gapminder$lifeExp, main = "Life Expectancy is positively related to GDP Per Capita", xlab = "GDP Per Capita", ylab = "Life Expectancy")
## > # 加上格線
## > grid()
1
2
3
4
5
6
7
8

為圖形加上 X 軸與 Y 軸的格線

在繪圖函數中指定參數 horiz = TRUE 調整圖形成為水平方向,其中 horiz 參數是 horizontal 的縮寫。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索各大洲的資料筆數
barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", ylab = "Continents", horiz = TRUE)
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索各大洲的資料筆數
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", ylab = "Continents", horiz = TRUE)
1
2
3
4
5
6

調整圖形成為水平方向

當我們將長條圖水平放置時,發現洲別的文字方向不適當,這時我們可以指定參數 las = 1 讓文字與座標軸垂直。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索各大洲的資料筆數
barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1)
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索各大洲的資料筆數
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1)
1
2
3
4
5
6

讓文字與座標軸垂直

當我們讓洲別文字與座標軸垂直之後發現 Americas 刻度文字被切去了開頭,我們可以指定參數 cex.name 將 Y 軸的刻度文字縮小一些。其中 cex 是 character expansion factor 的縮寫,指的是相對於預設值 1 的文字縮放倍數。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索各大洲的資料筆數
barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1, cex.name = 0.8)
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索各大洲的資料筆數
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1, cex.name = 0.8)
1
2
3
4
5
6

將 Y 軸的刻度文字縮小一些

## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索各大洲的資料筆數
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1, cex.name = 0.8, cex.axis = 1.2)
1
2
3
4
5
6

將 X 軸的刻度文字放大一些

density() 函數搭配 lines() 函數產生密度曲線,並調整直方圖的參數 freq = FALSE 來加上密度曲線。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 在直方圖加上標題與軸標籤
hist(gapminder$gdpPercap, main = "GDP Per Capita is left-skewed", xlab = "GDP Per Capita", ylab = "Density", freq = FALSE, ylim = c(0, 1.6e-04))
# 在直方圖加上密度曲線
lines(density(gapminder$gdpPercap))
1
2
3
4
5
6
7
8
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 在直方圖加上標題與軸標籤
## > hist(gapminder$gdpPercap, main = "GDP Per Capita is left-skewed", xlab = "GDP Per Capita", ylab = "Density", freq = FALSE, ylim = c(0, 1.6e-04))
## > # 在直方圖加上密度曲線
## > lines(density(gapminder$gdpPercap))
1
2
3
4
5
6
7
8

在直方圖上加上密度曲線

指定參數 pch 與 col 可以分別調整資料點的形狀與顏色,pch 是 plotting character 的縮寫,而 col 是 color 的縮寫。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索人均 GDP 與預期壽命之相關
plot(gapminder$gdpPercap, gapminder$lifeExp, main = "Life Expectancy is positively related to GDP Per Capita", xlab = "GDP Per Capita", ylab = "Life Expectancy", pch = 2, col = "red")
1
2
3
4
5
6
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索人均 GDP 與預期壽命之相關
## > plot(gapminder$gdpPercap, gapminder$lifeExp, main = "Life Expectancy is positively related to GDP Per Capita", xlab = "GDP Per Capita", ylab = "Life Expectancy", pch = 2, col = "red")
1
2
3
4
5
6

資料點改成紅色的空心三角形

實務應用會是以不同類別區分資料點的形狀與顏色,而非單純指定 pchcol 參數。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 探索人均 GDP 與預期壽命之相關
continent_pch <- as.numeric(gapminder$continent)
plot(gapminder$gdpPercap, gapminder$lifeExp, pch = continent_pch, col = gapminder$continent)
1
2
3
4
5
6
7
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 探索人均 GDP 與預期壽命之相關
## > continent_pch <- as.numeric(gapminder$continent)
## > plot(gapminder$gdpPercap, gapminder$lifeExp, pch = continent_pch, col = gapminder$continent)
1
2
3
4
5
6
7

以不同類別區分資料點的形狀與顏色

在呼叫繪圖函數之前先用 part(mfrow = c(m, n)) 將畫布切割為 mxn 個區塊,藉此將多個圖形繪畫在同一個畫布上,其中 mfrowmatrix of figures entered row-wise 的縮寫。

# 安裝 gapminder 套件
# install.packages("gapminder")
# 載入 gapminder 套件
library(gapminder)
# 將畫布切割為 2x2
par(mfrow = c(2, 2))
# 探索各大洲的資料筆數
barplot(table(gapminder$continent))
barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", ylab = "Continents", horiz = TRUE)
barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1)
barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1, cex.name = 0.6)
1
2
3
4
5
6
7
8
9
10
11
## > # 安裝 gapminder 套件
## > # install.packages("gapminder")
## > # 載入 gapminder 套件
## > library(gapminder)
## > # 將畫布切割為 2x2
## > par(mfrow = c(2, 2))
## > # 探索各大洲的資料筆數
## > barplot(table(gapminder$continent))
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", ylab = "Continents", horiz = TRUE)
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1)
## > barplot(table(gapminder$continent), main = "Number of Observations in Gapminder", xlab = "Number of Observations", horiz = TRUE, las = 1, cex.name = 0.6)
1
2
3
4
5
6
7
8
9
10
11

將多個圖形繪畫在同一個畫布上

我們可以利用 RStudio 介面中右下角的 Plots 頁籤點選 Export 輸出視覺化成為 PDF 或圖片檔格式,並調整輸出格式、路徑、檔名、長度與寬度。

輸出成為 PDF 或圖片檔格式

調整輸出格式、路徑、檔名、長度與寬度

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

小結

在這個小節中我們簡介以 R 語言實踐基礎探索資料分析,以內建繪圖系統 Base Plotting System 作資料視覺化,包含基礎的繪圖函數與常用的自訂元件。

練習

將一個畫布切割成為 2X2 個區塊,並使用 Base Plotting System 繪製任意四種圖形。

延伸閱讀