2015-09-06

About Me

Johnson Hsieh, PhD

  • DSP 智庫驅動 資料科學家 dsp.im
  • Data Science HC 共同創辦人 FB page
    • 教育訓練
    • 顧問諮詢
    • 社會服務

Why Use R?

R 來自世界上最專業的統計學家

R 可以輸出高品質的視覺化

R 有驚人彈性和潛力

R 很容易和其他工具整合

R 很容易擴充和客製化

本週目標

環境設定

  • 建立可以使用R 的環境
  • 了解R 的使用界面

學習R 語言

  • 透過實際的範例學習R 語言
    • 讀取資料
    • 選取資料
    • 敘述統計量與視覺化
  • 利用實例來傳授學習的心法

工欲善其事,必先利其器

傢俬準備好

環境設定

熟悉界面

  • 程式碼編輯區
  • 命令列區
  • 其他資訊區
  • 檔案系統區

熟悉RStudio的 命令列 界面

程式的輸入輸出中斷

  • 注意最左下腳的符號是 >
  • 輸入 "hello world" 後按下Enter,檢查螢幕輸出(記得加上引號)
  • 輸入 1 + 1 後按下Enter,檢查螢幕輸出,注意有無引號
  • 輸入 1 + 後按下Enter,檢查螢幕輸出,注意最左下角的開頭變成+
  • 按下Ctrl + C或ESC,檢查哪一個按鈕會讓左下角回復成>開頭
  • 在新的一行命令列區輸入 me 之後按下Enter
  • 在新的一行命令列區輸入 me 之後按下tab

熟悉RStudio的 程式碼編輯 界面

  • 請建立再編輯界面寫程式的習慣
  • 開啟新的R Script檔案
  • 在第一行輸入 me 隻後按下Ctrl + Enter後,觀察命令列區
  • 利用滑鼠點選 me 後的位置,確認游標閃爍的位置在 me 之後,按下tab

熟悉RStudio的其他頁面

請見現場示範

讓我們來說 R 語

敘述句

1; 2;
[1] 1
[1] 2
"1; 2;"
[1] "1; 2;"

筆記

  • 敘述句以 ;斷行 (輸入Enter) 作結尾
  • R 會把單引號 ' 或雙引號 " 所包覆的敘述當成字串
  • 沒有完成的敘述句,命令列的開頭會變成 +
  • 可以用 Ctrl + C 或 Esc 中斷敘述句

敘述句

# 基礎運算
1 + 2 + 3
[1] 6
1 +       2 + 3
[1] 6
x <- 10
y <- 4
(x + y) / 2 
[1] 7

筆記

  • 基本數學運算符號 (+, -, *, /, …)
  • 空白 (space) 不影響程式執行
  • Commands 以空行 (newline) 或分號 (;) 區隔
  • 箭號 (<-) 表示賦值,把箭號右邊的結果指向到R物件
  • R 的指令有大小寫的區分
  • 井號 (#) 表示註解,使得該行不執行運算

向量 (vector):R 最基礎的物件

  • c()表示 (c 取自combine之意), 元素以逗號分隔。
  • 連續整數向量可以利用 : (冒號) 簡記,譬如數列1, 2, 3 在 R 語言中可利用 1:3 簡記
  • 也可以透過seq函數生成有規則的數值向量(序列)
# basic expression of integer vector
c(1, 2, 3, 4)
[1] 1 2 3 4
# simple expression
1:4
[1] 1 2 3 4
4:1
[1] 4 3 2 1

向量 (vector):R 最基礎的物件2

  • c()表示 (c 取自combine之意), 元素以逗號分隔。
  • 連續整數向量可以利用 : (冒號) 簡記,譬如數列1, 2, 3 在 R 語言中可利用 1:3 簡記
  • 也可以透過seq函數生成有規則的數值向量(序列)
# use seq() function
seq(1, 4, 1)
[1] 1 2 3 4
seq(1, 9, by = 2) # 試著按tab鍵,執行自動補字
[1] 1 3 5 7 9
seq(1, 9, length.out = 5)
[1] 1 3 5 7 9

小挑戰

seq 函數列出偶數數列: 2, 4, 6, 8, 10

向量的 Recycling properties

recycling properties,便於執行四則運算。

# shorter arguments are recycled
1:3 * 2
[1] 2 4 6
1:4 + 1:2
[1] 2 4 4 6
c(0.5, 1.5, 2.5, 3.5) * c(2, 1)
[1] 1.0 1.5 5.0 3.5

Warning message:

# warning (why?)
1:3 * 1:2
Warning in 1:3 * 1:2: 較長的物件長度並非較短物件長度的倍數
[1] 1 4 3
1:3 + 1:4
Warning in 1:3 + 1:4: 較長的物件長度並非較短物件長度的倍數
[1] 2 4 6 5

小挑戰

向量的四則運算,請計算以下五位女藝人的BMI Hint:

height <- c(174, 158, 160, 168, 173)
weight <- c(52, 39, 42, 46, 48)

在 R 中查詢說明文件

各種自救措施

help.start()
ab # 輸入`ab`後 按下tab
?abs   # 等同於 help(abs)
??abs 
apropos("abs")
example(abs)
vignette()
vignette("Introduction", "Matrix")



筆記

  • help.start: 說明檔首頁
  • 自動完成 (tab鍵):列出所有ab開頭的函數
  • ? (一個問號):查詢特定函數的說明檔
  • ?? (兩個問號):查詢包含特定關鍵字的說明檔
  • apropos : 查詢包含特定關鍵字的函數
  • example : 執行特定函數的使用範例
  • vignette : 查詢R環境中各種介紹文件

常用資料分析函數

統計量: sum, mean, abs, sd, length, table, cut, …

x <- c(174, 158, 160, 168, 173)
sum(x)    # 向量元素加總
[1] 833
length(x) # 向量長度 (包含幾個元素)
[1] 5
mean(x)   # 平均數 等價於 sum(x) / length(x)
[1] 166.6
abs(x - mean(x)) / sd(x) # T統計量
[1] 1.0088825 1.1724850 0.8998141 0.1908697 0.8725470

常用資料分析函數2

統計量: sum, mean, abs, sd, length, table, cut, …

a <- runif(20, 1, 100) # 隨機抽取20筆介於1~100的亂數
cut(a, c(1,20,40,60,80,100)) # 依據給定的breaks對數值資料做分組
 [1] (60,80]  (20,40]  (1,20]   (60,80]  (80,100] (20,40]  (1,20]  
 [8] (20,40]  (1,20]   (40,60]  (60,80]  (80,100] (1,20]   (40,60] 
[15] (20,40]  (40,60]  (80,100] (1,20]   (20,40]  (20,40] 
Levels: (1,20] (20,40] (40,60] (60,80] (80,100]
table(c("a", "a", "b", "c", "b", "a"))
a b c 
3 2 1 

常用資料分析函數3

排序: order vs. sort

order(x) # 取得物件x各元素大小排序之順序 (由小到大)
[1] 2 3 4 5 1
x[order(x)]
[1] 158 160 168 173 174
x[order(x, decreasing = TRUE)]  # 由大到小排序
[1] 174 173 168 160 158
sort(x) 
[1] 158 160 168 173 174
sort(x, decreasing = TRUE)
[1] 174 173 168 160 158
# `sort` 函數:直接對元素排序
# `order` 函數:取得元素排序後的順序

常用資料分析函數4

重抽: sample

sample(x)    # 對x做重新排序
[1] 168 158 174 160 173
sample(1:5)
[1] 1 4 5 2 3
sample(1:5, size = 3) # 從1:5中任取3個值(不重複)
[1] 5 1 3
sample(1:5, size = 3, replace = TRUE) # 從1:5中任取3個值(可重複)
[1] 5 4 5

向量的取值、取代與新增

  • 利用[ ] (中括號) 、比較運算子(>, <, >=, <=, ==, !=)、邏輯運算子 (&, |) 以及負號 (-) 進行向量的取值。
x <- c(174, 158, 160, 168, 173)
x[1]           # 選取第1個位置的元素
[1] 174
x[c(1, 3)]     # 選取第1, 3個位置的元素
[1] 174 160
x[c(2, 3, 1)]  # 選取第2, 3, 1個位置的元素 (依照順序)
[1] 158 160 174
# 在[ ]中使用負號 (-) 移除給定位置元素 (反向選取)
x[-1]
[1] 158 160 168 173
x[-c(1, 3, 4)]
[1] 158 173

向量的取值、取代與新增2

  • 利用[ ] (中括號) 、比較運算子(>, <, >=, <=, ==, !=)、邏輯運算子 (&, |) 以及負號 (-) 進行向量的取值。
  • 利用 [ ] (中括號) 與 <- (箭號) 進行取代與新增元素
# 使用比較運算子 加上 `which` 函數進行取值
x > 160
[1]  TRUE FALSE FALSE  TRUE  TRUE
index <- which(x > 160) # 滿足條件的位置為TRUE,反之為FALSE
x[index]
[1] 174 168 173
# 指令壓縮,將指令寫在 [ ] 中,以達到縮短程式碼的功效
x[which(x > 160)]
[1] 174 168 173
# 也可以使用邏輯算子進行取值
x[x > 160 & x < 170] # 選取位置為TRUE的位置
[1] 168

小挑戰

利用指令壓縮的方式取得 x大於170 或 x小於160 的元素
Hint: 使用邏輯算子 or (|)

向量的取值、取代與新增3

  • 利用 [ ] (中括號) 與 <- (箭號) 進行取代與新增元素
#' ## 元素的取代
x[2] <- 158.5 # 取代x物件的第二個元素
x
[1] 174.0 158.5 160.0 168.0 173.0
x[c(1,3)] <- 0 # 取代第一、三個元素為 0
x[6] <- 166    # 新增第六個元素為 166
# 等價於 c(x, 166) 
x
[1]   0.0 158.5   0.0 168.0 173.0 166.0
x[x > 160] <- 170 # 取代大於160的值為170
x
[1]   0.0 158.5   0.0 170.0 170.0 170.0

R 的資料架構

  • R 包含三種基本資料型態 (class):
    1. 數值 (numeric vector): x <- c(174, 158, 160, 168, 173)
    2. 字串 (character vector): y <- c("林志玲", "蔡依林", "楊丞琳", "天心", "隋棠")
    3. 邏輯 (logical vector): z <- c(TRUE, FALSE, FALSE, FALSE, TRUE)
  • 利用class函數判斷物件型態
  • character vector,以雙引號 " " 或單引號 ' ' 註記
  • logical vector,以TRUE / FALSE 註記,亦可簡化為 T / F
class(x); class(y); class(z)
[1] "numeric"
[1] "character"
[1] "logical"

資料型態的轉換

  • 物件一次只能接受一種型態
  • 若同時在一個向量中給定多種型態,R 將會依以下順序進行自動轉換:字串 > 數值 > 邏輯。
  • 也可以利用以下函數自行轉換向量的型態:as.character, as.numeric, as.logical
# 向量只容許一種類別 (字串 > 數值 > 邏輯)
c(174, 52, "林志玲") # 數值被轉換成字串

# 布林值 TRUE 被轉換成1,FALSE被轉換成0
c(174, 52, TRUE) 
c(1.1, 2.4, TRUE, FALSE)

# 所有元素都被轉換成字串
c("林志玲", 174, 52, TRUE)

# 字串轉數字
a1 <- c("89", "91", "102")
as.numeric(a1)

資料型態的轉換2

  • 物件一次只能接受一種型態
  • 若同時在一個向量中給定多種型態,R 將會依以下順序進行自動轉換:字串 > 數值 > 邏輯。
  • 也可以利用以下函數自行轉換向量的型態:as.character, as.numeric, as.logical
# 布林轉數字
a2 <- c(TRUE, TRUE, FALSE)
as.numeric(a2)

# 數字轉布林
a3 <- c(-2, -1, 0, 1, 2) # 只有0會被轉成FALSE
as.logical(a3)

# 數字轉字串
as.character(a3)

特殊資料型態

  • 特殊的數值型態:時間
Sys.time() # "2015-09-03 08:50:24 CST"
[1] "2015-09-06 15:14:14 CST"
  • 特殊的字串型態:類別
factor(c("male", "female", "female", "male"))
[1] male   female female male  
Levels: female male

類別 (factor) 物件簡介

當一向量變數是類別型變數 (譬如:性別、教育水準) 時,在R語言中以factor進行定義。

# variable gender with 2 "male" entries and 3 "female" entries 
# rep(x, n) 函數能重複x物件n次
gender <- c(rep("male",2), rep("female", 3)) 
gender
[1] "male"   "male"   "female" "female" "female"
gender <- factor(gender)
gender
[1] male   male   female female female
Levels: female male
levels(gender) 
[1] "female" "male"  

類別 (factor) 物件簡介2

  • 可使用 as.numeric 將factor物件轉換成數值
  • factor 函數中有個多的參數可以進行設定
# 1=female, 2=male internally (alphabetically)
as.numeric(gender) 
[1] 2 2 1 1 1
# change vector of labels for the levels
factor(gender, levels=c("male", "female"), labels=c("M", "F"))
[1] M M F F F
Levels: M F
# 類別轉字串
as.character(gender)
[1] "male"   "male"   "female" "female" "female"

資料型態的轉換3

將數值轉換為類別

# 利用cut對資料做分級
x <- c(75, 81, 82, 76, 91, 92)
cut(x, breaks = c(70, 80, 90, 100))
[1] (70,80]  (80,90]  (80,90]  (70,80]  (90,100] (90,100]
Levels: (70,80] (80,90] (90,100]



資料型態的轉換 - 將字串轉換為數值

x <- c("1", "2", "3", "2", "a")
as.numeric(x)
Warning: 強制變更過程中產生了 NA
[1]  1  2  3  2 NA
  • NA代表Not available,代表著missing value

資料型態的轉換 - 資料清理

民國80年至82年的國民生產毛額


百萬元
5,023,763
5,614,679
6,205,338
gdp <- c("5,023,763", "5,614,679", "6,205,338")
as.numeric(gsub(",", "", gdp))
[1] 5023763 5614679 6205338

小挑戰

將民國年 (字串) 轉為 西元年 (數值)

year <- c("民國101", "民國102", "民國103", "民國104")

R 是向量式

  • 所有的資料都是向量
  • 上述介紹的整數、實數、字串和類別型都是相同型態的向量
  • list是R 物件的向量
  • data.frame是長度相同的R 物件的向量

data.frame是最常使用的物件

  • data.frame的概念在各種資料處理的領域非常常見
    • 例:資料庫
  • (實務經驗)R 使用者會希望能透過前處理把資料轉換為data.frame的型式
  • R 提供將資料匯入成data.frame的功能
  • R 提供自data.frame開始的各種進階處理功能
    • 資料的整理
    • 圖形的繪製
    • 模型的配適與預測

小挑戰

  • 請問根據以下的輸出,這份ubike的各欄類別為何?
date character tot integer min.bemp integer
hour integer avg.sbi numeric std.bemp numeric
sno integer max.sbi integer temp numeric
sarea character min.sbi integer humidity numeric
sna character std.sbi numeric pressure numeric
lat numeric avg.bemp numeric max.anemo numeric
lng numeric max.bemp integer rainfall numeric

小挑戰

  • 請問根據中文名稱,這份ubike的各欄類別是否合理?
日期 character 總停車格 integer 最小空位數 integer
時間 integer 平均車輛數 numeric 空位數標準差 numeric
場站代號 integer 最大車輛數 integer 平均氣溫 numeric
場站區域 character 最小車輛數 integer 溼度 numeric
場站名稱 character 車輛數標準差 numeric 氣壓 numeric
緯度 numeric 平均空位數 numeric 最大風速 numeric
經度 numeric 最大空位數 integer 降雨量 numeric

資料的讀取

讀取表格檔案 - 0. 先抓取資料

讀取表格檔案 - 1. 先檢視資料

# path <- "data/ubikeweatherbig5.csv"
path <- file.choose()
readLines(path, n = 5)

讀取表格檔案 - 2. 讀取資料

  • 先讀取一部分,再讀取全部
ubike <- read.table(path, sep = ",", header = TRUE, nrows = 100)
head(ubike)
ubike <- read.table(path, sep = ",", header = TRUE, 
  colClasses = c("factor", "integer", "integer", "factor", "factor", 
    "numeric", "numeric", "integer", "numeric", "integer", "integer", 
    "numeric", "numeric", "integer", "integer", "numeric", "numeric", 
    "numeric", "numeric", "numeric", "numeric"))
# object.size(ubike) # 約86MB

常見的讀取錯誤1

路徑錯誤

path <- "wrong_path"
power <- read.table(file = path, header = TRUE, sep = ",")
Error in file(file, "rt") : 無法開啟連結
此外: Warning message:
In file(file, "rt") : 無法開啟檔案 'wrong_path' :No such file or directory
  • 絕對路徑
    • 確認檔案是否存在
  • 相對路徑
    • 利用getwd了解R 當下的路徑位置

常見的讀取錯誤2

格式錯誤

path <- "data/ubikeweatherbig5.csv"
power <- read.table(file = path, header = TRUE, sep = "1")
Error in read.table(file = path, header = TRUE, sep = "1") : 
  more columns than column names
  • 利用其他編輯器確認分隔符號
  • 確認每列的資料的欄位是正確的
    • 必要時,請用其他文件編輯器校正欲讀取的檔案

常見的讀取錯誤3

編碼錯誤

path <- "data/ubikeweatherbig5.csv"
power <- read.table(file = path, header = TRUE, sep = ",", nrows = 10)
錯誤在type.convert(data[[i]], as.is = as.is[i], dec = dec, numerals = numerals,  : 
  無效的多位元組字串於 '<ab>H<b8>q<b0><cf>'
  • 查詢檔案的編碼
    • 常見的中文編碼有UTF-8BIG-5
    • 讀取時套上file函數指定編碼
    • 組合readLinesiconvwrite來製造符合系統編碼的檔案

ubike是一種data.frame

class(ubike)
[1] "data.frame"

校正欄位名稱

colnames(ubike) <- 
  c("日期", "時間", "場站代號", "場站區域", "場站名稱", 
  "緯度", "經度", "總停車格", "平均車輛數", "最大車輛數", 
  "最小車輛數", "車輛數標準差", "平均空位數", "最大空位數", 
  "最小空位數", "空位數標準差", "平均氣溫", "溼度", 
  "氣壓", "最大風速", "降雨量")

存取資料庫: SQLite

# install.packages("RSQLite")
library(RSQLite)
Loading required package: DBI
db.path <- "ubike.db"
drv <- dbDriver("SQLite")
db <- dbConnect(drv, db.path)
dbWriteTable(db, "ubike", head(ubike))
dbListTables(db)
dbReadTable(db, "ubike")
dbDisconnect(db)

未來的學習清單

各式資料庫的連接

  • SQL Database: RMySQL, RPostgreSQL, ROracle, RJDBC, RODBC
  • No SQL Database: rmongodb, rredis
  • 讀取XML和網頁資料
    • XML套件和XPath
  • 讀取json資料
    • RJSONIO套件

資料的選取

表格的選取 - 座標

ubike[2, 3]
[1] 2
        日期 時間 場站代號
1 2014-12-08   15        1
2 2014-12-08   15        2
3 2014-12-08   15        3
4 2014-12-08   15        4
5 2014-12-08   15        5
6 2014-12-08   15        6

表格的選取 - 欄

head(ubike[["日期"]]) 
[1] "2014-12-08" "2014-12-08" "2014-12-08" "2014-12-08" "2014-12-08"
[6] "2014-12-08"
# head(ubike$日期)
head(ubike[,1])
[1] "2014-12-08" "2014-12-08" "2014-12-08" "2014-12-08" "2014-12-08"
[6] "2014-12-08"

範例

取出場站代號為1的所有資料

  1. ubike選取場站代號
  2. 將結果1.輸入至函數unique
  3. 利用布林運算,把1.的結果和1比較
  4. 將結果3.輸入至函數which
  5. 利用3.和4.的結果選取ubike的列
ans1 <- ubike[["場站代號"]]
ans2 <- unique(ans1)
ans3 <- ans1 == 1
ans4 <- which(ans3)
ans5 <- ubike[ans3,]
ans5 <- ubike[ans4,]

小挑戰

  • 請查詢場站代號1099所在的行政區
  • 請查詢場站代號1099的氣溫
    1. ubike選取場站代號
    2. 利用布林運算,把1.的結果和1099比較
    3. ubike選取2.的列之後,用1.的方法選取平均氣溫 3.1 可利用座標的概同時選取出結果

指令的壓縮

  • 請大家學習「被壓縮的程式碼」該如何解讀
    • 掌握運算符號的運算順序
ubike[ubike[["場站代號"]] == 1 & ubike[["日期"]] == "2015-03-01",]

x1 <- ubike[["場站代號"]] == 1
x2 <- ubike[["日期"]] == "2015-03-01"
x3 <- x1 & x2
x4 <- ubike[x3,]

2014 年最有影響的套件之一:magrittr

  • 壓縮的程式碼不好讀
  • 展開的程式碼會產生很多暫存變數
  • 套件magrittr部份解決了這個問題
  • 請參考Johnson於DSHC meetup的套件介紹
ans1 <- ubike[["場站代號"]]
ans1.1 <- unique(ans1)

unique(ubike[["場站代號"]])

# install.packages("magrittr")
library(magrittr)
ubike[["場站代號"]] %>%
  unique

2014 年最有影響的套件之一:dplyr

  • 讓R 使用者可以用更有彈性的方式來處理資料
  • 針對data.frame做設計(名稱中的d
  • 設計理念
    • 導入資料整理最重要的動作(非常類似SQL)
    • 支援異質資料源(data.frame或資料庫中的表格)

學習dplyr的官方方式:vignette

vignette(all = TRUE, package = "dplyr")
vignette("introduction", package = "dplyr")
  • 更詳細的dplyr介紹可以閱讀dplyr的小論文
  • R 的開發者會針對一個主題撰寫小論文做介紹

dplyr簡介

資料的探索

挑戰:學習sd的用法

  • 透過?sd嘗試自學標準差的用法
  • 選取場站代號為1和日期為"2015-03-01"的資料
  • 計算捷運市政府站(3號出口)"2015-03-01"降雨量的標準差
x1 <- ubike[["場站代號"]] == 1
x2 <- ubike[["日期"]] == "2015-03-01"
ubike[x1 & x2, "降雨量"]
 [1] 0.000 0.432 0.702 0.947 1.129 1.224 1.241 1.218 1.201 1.207 1.225
[12] 1.233 1.227 1.218 1.220 1.233 1.244 1.246 1.242 1.242 1.249 1.257
[23] 1.258 1.252
sd(ubike[x1 & x2, "降雨量"])
[1] 0.3078623

挑戰:學習sd的用法

  • 練習使用dplyr & pipes
library(dplyr)
sd(select(
  filter(ubike, 場站代號 == 1, 日期 == "2015-03-01"),
  降雨量)[["降雨量"]])

filter(ubike, 場站代號 == 1, 日期 == "2015-03-01") %>%
  select(降雨量) %>%
  extract2("降雨量") %>%
  sd

各行政區的站點數: group_by


每日的平均雨量

group_by(ubike, 日期) %>%
  summarise(平均降雨量 = mean(降雨量))

各行政區的站點數: group_by

各場站區域的站點數

group_by(ubike, 場站區域) %>%
  summarise(站點數 = length(unique(場站代號))) %>%
  arrange(站點數)

各場站區域的站點代號清單

group_by(ubike, 場站區域) %>%
  summarise(站點代號清單 = paste(unique(場站代號), collapse = ","))

小挑戰

探索一個質化變數,利用table列出所有的場站名稱出現的次數

探索變數間的關係

  • ftable:質化 v.s. 質化
  • bar chart:質化 v.s. 量化
  • scatter plot: 量化 v.s. 量化

探索質化變數與質化變數的關係

?ftable
example(ftable)
ftable> ## Start with a contingency table.
ftable> ftable(Titanic, row.vars = 1:3)
                   Survived  No Yes
Class Sex    Age                   
1st   Male   Child            0   5
             Adult          118  57
      Female Child            0   1
             Adult            4 140

小挑戰:

  1. 選取場站區域為信義區且日期為"2015-03-01"的列
  2. 選取欄平均車輛數總停車格
  3. 利用布林運算式計算"平均車輛數"是否超過總停車格的一半
    • 命名為空位較多
  4. 選取欄時間
  5. 比較時間空位較多的交互關係

小挑戰(參考答案)

x1 <- ubike[["場站區域"]] == "信義區"
x2 <- ubike[["日期"]] == "2015-03-01"
x3 <- ubike[x1 & x2, "平均車輛數"]
x4 <- ubike[x1 & x2, "總停車格"]
x5 <- x3 < x4 / 2
x6 <- ubike[x1 & x2, "時間"]
ftable(x6, x5)

x1 <- filter(ubike, 場站區域 == "信義區", 日期 == "2015-03-01")
x2 <- mutate(x1, 空位較多 = 平均車輛數 < 總停車格 / 2)
ftable(x2[["時間"]], x2[["空位較多"]])

tbl <- filter(ubike, 場站區域 == "信義區", 日期 == "2015-03-01")  %>%
  mutate(空位較多 = 平均車輛數 < 總停車格 / 2)
ftable(tbl[["時間"]], tbl[["空位較多"]])

Data Visualization with ggplot

Data Visualization

  • 清晰有效地傳達與溝通訊息
  • 教學、研究、宣傳
  • 美學、功能兼顧
  • 統計圖形、訊息可視化
  • 參考Johnson於DSHC meetp的介紹

ggplot

  • 當前最多人使用的視覺化R套件
  • 取自 “The Grammar of Graphics” (Leland Wilkinson, 2005)
  • 由Hadley Wickham於2005年發表 (Chief Scientist in RStudio)
  • 設計理念
    • 採用圖層系統
    • 用抽象的概念來控制圖形,避免細節繁瑣
    • 圖形美觀

ggplot2的基本架構

  • 資料 (data) 和映射 (mapping)
  • 幾何對象 (geometric)
  • 座標尺度 (scale)
  • 統計轉換 (statistics)
  • 座標系統 (coordinante)
  • 圖層 (layer)
  • 刻面 (facet)
  • 主題 (theme)

ggplot2的基本架構

基本語法

ggplot(data=..., aes(x=..., y=...)) + geom_xxx(...) +
  stat_xxx(...) + facet_xxx(...) + ...
  • ggplot 描述 data 從哪來
  • aes 描述圖上的元素跟 data 之類的對應關係
  • geom_xxx 描述要畫圖的類型及相關調整的參數 常用的類型諸如:geom_bar, geom_points, geom_line

注意

使用 data.frame 儲存資料 (不可以丟 matrix 物件) 使用 long format (利用reshape2套件將資料轉換成 1 row = 1 observation)

質化 v.s. 量化:繪圖之前的整理資料

信義區各站點在"2015-02"的平均降雨量

# grepl("要搜尋的字串", x, fixed = TRUE)
x1.1 <- grepl("2015-02", ubike[["日期"]], fixed = TRUE)
x1.2 <- ubike[["場站區域"]] == "信義區"
x2 <- group_by(ubike[x1.1,], 場站名稱)
x3 <- summarise(x2, 平均降雨量 = mean(降雨量))

x3 <- filter(ubike, grepl("2015-02", 日期, fixed = TRUE), 
             場站區域 == "信義區") %>%
  group_by(場站名稱) %>% summarise(平均降雨量=mean(降雨量))

質化 v.s. 量化:barchart

thm <- theme(text=element_text(size=18)) + theme_gray(base_family = "STHeiti")
las2 <- theme(axis.text.x = element_text(angle = 90, hjust = 1))

ggplot(x3) +
  geom_bar(aes(x = 場站名稱, y = 平均降雨量), stat = "identity") +
  thm + las2

質化 v.s. 量化:boxplot

x1.1 <- grepl("2015-02", ubike[["日期"]], fixed = TRUE)
x1.2 <- ubike[["場站區域"]] == "信義區"
x2 <- group_by(ubike[x1.1,], 場站名稱)
# x3 <- summarise(x2, 平均降雨量 = mean(降雨量))

x3 <- filter(ubike, grepl("2015-02", 日期, fixed = TRUE), 
             場站區域 == "信義區") # %>%
#  group_by(場站名稱) %>% summarise(平均降雨量=mean(降雨量))

ggplot(x3) +
  geom_boxplot(aes(x = 場站名稱, y = 降雨量)) +
  thm + las2

量化 v.s. 量化:繪圖之前的整理資料

信義區各站點在"2015-02"的平均溼度 vs. 平均雨量

# grepl("要搜尋的字串", x, fixed = TRUE)
x1.1 <- grepl("2015-02", ubike[["日期"]], fixed = TRUE)
x1.2 <- ubike[["場站區域"]] == "信義區"
x2 <- group_by(ubike[x1.1,], 場站名稱)
x3 <- summarise(x2, 平均降雨量 = mean(降雨量), 平均溼度 = mean(溼度))

x3 <- filter(ubike, grepl("2015-02", 日期, fixed = TRUE), 
             場站區域 == "信義區") %>%
  group_by(場站名稱) %>% summarise(平均降雨量 = mean(降雨量), 平均溼度 = mean(溼度))

量化 v.s. 量化:Scatter Plot

  • 原因在x軸,結果在y軸
ggplot(x3) +
  geom_point(aes(x = 平均溼度, y = 平均降雨量)) +
  thm + las2

量化 v.s. 量化:Grouped Scatter Plot

ggplot(x3) +
  geom_point(aes(x = 平均溼度, y = 平均降雨量, colour = 場站名稱)) +
  thm + las2

相關資源

圖表的輸出

輸出圖片

  • Rstudio UI
  • savePlot
  • bmppngjpegtiff
  • ggsave

輸出表格

  • write.csv
  • xtable套件

總結

本週目標

環境設定

  • 建立可以使用R 的環境
  • 了解R 的使用界面

學習R 語言

  • 透過實際的範例學習R 語言
    • 讀取資料
    • 選取資料
    • 敘述統計量與視覺化
  • 利用實例來傳授學習的心法

掌握心法後,如何自行利用R 解決問題

你喜歡R 嗎?

  • R 是由一群來自世界上的志工貢獻而成的
  • 你覺得R 有不好用的地方嗎?
    • 歡迎聯絡我,讓我們一起來貢獻,改進R 的使用體驗