1 課程目標

本週上課將介紹Rdplyr的套件中的指令,包括selectfiltermutate等函數,協助研究者整理資料,並且轉置資料。例如:

library(dplyr)
students<-read.table('studentsfull.txt', sep='', header=TRUE)
students.part<-mutate(students, sex=as.numeric(Gender)-1)
students.part
##          ID     Name Department Score Gender sex
## 1  10322011    Ariel  Aerospace    78      F   0
## 2  10325023    Becky    Physics    86      F   0
## 3  10430101     Carl Journalism    69      M   1
## 4  10401032  Dimitri    English    83      M   1
## 5  10307120  Enrique  Chemistry    80      M   1
## 6  10207005 Fernando  Chemistry    66      M   1
## 7  10305019   George  Mechanics    75      F   0
## 8  10305022   Howell  Mechanics    81      M   1
## 9  10305029      Ian  Mechanics    60      M   1
## 10 10305031    Julio  Mechanics    89      M   1
## 11 10322014    Kaori  Aerospace    82      F   0
## 12 10425026     Luke    Physics    88      M   1
## 13 10401022   Miguel    English    92      M   1
## 14 10501006      Neo    English    77      M   1
## 15 10321010   Olivia  Economics    85      F   0
## 16 10321011    Peter  Economics    88      M   1
## 17 10405017     Qing  Mechanics    88      F   0
## 18 10422007    Ricky  Aerospace    91      M   1
## 19 10422008    Seiko  Aerospace    80      F   0
## 20 10430005  Terresa Journalism    62      F   0
## 21 10530009     Usla Journalism    87      F   0
## 22 10421001   Vivian  Economics    70      F   0
## 23 10307018    Wendy  Chemistry    85      F   0
## 24 10425003     Xing    Physics    93      M   1
## 25 10221030     Yoko  Economics    66      F   0
## 26 10430015      Zoe Journalism    92      F   0

2 資料的型態

之前我們學習R的基礎指令,而dplyr提供許多指令幫我們整理資料。Hadley Wickman 發展了plyr套件,然後又發展dplyr套件。為了節省時間,我們直接討論dplyr的幾個實用的函數。

2.1 tibble

在下載dplyr套件之後,請嘗試這個指令:

library(dplyr)
tibble(
  s=c("all","at","air","age", "angle"),
  x = 1:5, 
  y = 1, 
  z = x  + y,
  )
## # A tibble: 5 x 4
##   s         x     y     z
##   <chr> <int> <dbl> <dbl>
## 1 all       1    1.    2.
## 2 at        2    1.    3.
## 3 air       3    1.    4.
## 4 age       4    1.    5.
## 5 angle     5    1.    6.

或者是:

data_frame(s=c("all","at","air","age", "angle"), x = 1:5, y = 1, z = x  + y)
## # A tibble: 5 x 4
##   s         x     y     z
##   <chr> <int> <dbl> <dbl>
## 1 all       1    1.    2.
## 2 at        2    1.    3.
## 3 air       3    1.    4.
## 4 age       4    1.    5.
## 5 angle     5    1.    6.

tibble是一個新的資料型態,比資料框(data.frame)多了變數的資訊,而且會顯示前面十個觀察值的資訊,以及螢幕剛好足夠容納的下的變數。例如打開pp0797B2.sav這個檔案,但是把它視為tibble而不是data.frame:

library(foreign)
setwd("~/Library/Mobile Documents/com~apple~CloudDocs/eastasia")
pp0797b2<-read.spss('PP0797B2.sav', to.data.frame=TRUE)
tibble_pp0797b2<-as_tibble(pp0797b2)
tibble_pp0797b2
## # A tibble: 2,058 x 24
##    Q1     Q2     Q3     Q4     Q5    Q6    Q7    Q8    Q9    Q10   partyid
##    <fct>  <fct>  <fct>  <fct>  <fct> <fct> <fct> <fct> <fct> <fct> <fct>  
##  1 很難說 同意   不同意 同意   同意  不同意… 同意  不相信… 不同意… 不同意… 國民黨 
##  2 非常不同意… 非常同意… 不同意 同意   很難說… 不同意… 不同意… 不相信… 不同意… 不同意… 中立及看情形…
##  3 非常不同意… 非常同意… 非常不同意… 非常同意… 同意  非常同意… 不同意… 不相信… 不同意… 不同意… 中立及看情形…
##  4 同意   同意   不同意 同意   不同意… 非常不同… 不同意… 很難說… 不同意… 非常同意… 民進黨 
##  5 非常不同意… 同意   不同意 不同意 不同意… 不同意… 同意  不相信… 同意  非常不同… 國民黨 
##  6 不同意 不同意 同意   同意   同意  同意  同意  不相信… 不同意… 非常同意… 中立及看情形…
##  7 非常不同意… 同意   不同意 不同意 不同意… 不同意… 非常同意… 非常不相… 不同意… 非常同意… 中立及看情形…
##  8 非常不同意… 非常同意… 非常不同意… 非常同意… 不同意… 不同意… 同意  非常相信… 不同意… 不同意… 民進黨 
##  9 同意   非常不同意… 非常同意… 不同意 非常不同… 不同意… 非常同意… 相信  不同意… 非常同意… 民進黨 
## 10 不同意 不同意 不同意 同意   不同意… 非常不同… 同意  不相信… 不同意… 不同意… 民進黨 
## # ... with 2,048 more rows, and 13 more variables: PARTY <fct>,
## #   tondu <fct>, ethnic <fct>, age <fct>, edu <fct>, sengiF <fct>,
## #   sengiM <fct>, CAREER <fct>, CAREER8 <fct>, TOWNID <dbl>, arear <fct>,
## #   sex <fct>, w <dbl>

可以看出tibble比較適用於大量的資料,讓資料分析更加容易。
也可以用print功能,決定輸出幾個觀察值以及決定螢幕寬度。

tibble_pp0797b2 %>%
  print(n=5, width=100)
## # A tibble: 2,058 x 24
##   Q1     Q2     Q3     Q4     Q5     Q6    Q7    Q8    Q9    Q10   partyid
##   <fct>  <fct>  <fct>  <fct>  <fct>  <fct> <fct> <fct> <fct> <fct> <fct>  
## 1 很難說 同意   不同意 同意   同意   不同意… 同意  不相信… 不同意… 不同意… 國民黨 
## 2 非常不同意… 非常同意… 不同意 同意   很難說 不同意… 不同意… 不相信… 不同意… 不同意… 中立及看情形…
## 3 非常不同意… 非常同意… 非常不同意… 非常同意… 同意   非常同意… 不同意… 不相信… 不同意… 不同意… 中立及看情形…
## 4 同意   同意   不同意 同意   不同意 非常不同… 不同意… 很難說… 不同意… 非常同意… 民進黨 
## 5 非常不同意… 同意   不同意 不同意 不同意 不同意… 同意  不相信… 同意  非常不同… 國民黨 
##   PARTY  tondu    ethnic
##   <fct>  <fct>    <fct> 
## 1 偏國民黨… 維持現狀,以後… 都是  
## 2 中立無反應… 維持現狀,看情… 台灣人
## 3 中立無反應… 永遠維持現狀… 都是  
## 4 普通支持民… 維持現狀,看情… 台灣人
## 5 非常支持國… 維持現狀,以後… 都是  
## # ... with 2,053 more rows, and 10 more variables: age <fct>, edu <fct>,
## #   sengiF <fct>, sengiM <fct>, CAREER <fct>, CAREER8 <fct>, TOWNID <dbl>,
## #   arear <fct>, sex <fct>, w <dbl>

而tibble格式的資料子集合可以是該變數的格式,也可以是資料框,可以用參數drop加以控制。例如:

class(tibble_pp0797b2[,1])
## [1] "tbl_df"     "tbl"        "data.frame"
class(tibble_pp0797b2[,1, drop=TRUE])
## [1] "factor"

2.1.1 簡潔數據(tidy dataset)

那麼,tibble的用處是什麼?tibble 來自於Hadley Wickham 發展的簡潔數據(tidy dataset)概念,簡潔數據的目標是讓每一個變數都有一個欄位(每一欄都是一個變數),而且每一筆觀察值都有一列,而且每一個值都有一儲存格(也就是每一個儲存格只有一個值,沒有例如\(a/b\)是由兩個值所構成)。詳見Garrett Grolemund & Hadley Wicham (http://r4ds.had.co.nz/index.html)。 tidy dataset也希望資料在同一個表,而非來自於不同的表。
雖然以下的指令適用於資料框以及整潔數據,但是整潔數據方便大數據分析。例如我們想要pp0797b2這筆資料加權之後的性別統計:

tibble_pp0797b2 %>% 
  count(sex, wt=w)
## # A tibble: 2 x 2
##   sex       n
##   <fct> <dbl>
## 1 男性  1031.
## 2 女性  1027.

Hadley Wickham也是ggplot2的作者,因此tibble資料適合於ggplot2的視覺化,例如我們想呈現性別的分佈,不一定用得到tibble:

library(ggplot2)
ggplot(tibble_pp0797b2, aes(x=sex)) +
  geom_bar(stat='count', fill='steelblue') +
  theme(text=element_text(family="HanWangMingBold", size=14))

但是要呈現兩個變數之間的相關程度(也就是聯合機率的次數),我們需要計算兩個變數的每一個類別的交叉,然後可以更容易使用ggplot2。以性別與首先計算性別類別下的民族認同(台灣人、中國人、都是、無反應),存成tibble格式的資料:

df.ethnic<-tibble_pp0797b2 %>%
      group_by(sex) %>%
      count(ethnic)
df.ethnic
## # A tibble: 8 x 3
## # Groups:   sex [2]
##   sex   ethnic     n
##   <fct> <fct>  <int>
## 1 男性  台灣人   379
## 2 男性  都是     469
## 3 男性  中國人    63
## 4 男性  無反應    66
## 5 女性  台灣人   377
## 6 女性  都是     574
## 7 女性  中國人    68
## 8 女性  無反應    62

上述指令中的%>%被稱為pipeline,有點像是兩行指令之間的連結,讓語法看起來更優雅。
接下來用tibble格式的df.ethnic 畫直方圖:

g<-ggplot(df.ethnic, aes(sex, n, fill=ethnic)) +
  geom_bar(stat='identity') +
  theme(text=element_text(family="HanWangMingBold", size=14))
g

由此可以看出,tibble資料以及dplyr的指令可以直覺式地處理資料。

3 非摘要式指令

dplyr指令可以產生新的變數,也可以產生統計的結果。首先介紹轉換資料但是不產生統計摘要(例如平均值、最小值、最大值等等)結果的指令。

3.1 挑選特定欄位(select)

在一個二維的資料型態,假設我們想留下部分欄位的資料,捨棄其他欄位,可以用select這個函數。例如:

library(dplyr)
dt <- tibble(
  s=c("B", "B", "A","B","A","C", "B", "B","B", "B", "A","B","A","C", "B", "B"),
  x = 1:16, 
  y = 1, 
  z = x  + 2*y,
  )
dt %>% select(z, s)
## # A tibble: 16 x 2
##        z s    
##    <dbl> <chr>
##  1    3. B    
##  2    4. B    
##  3    5. A    
##  4    6. B    
##  5    7. A    
##  6    8. C    
##  7    9. B    
##  8   10. B    
##  9   11. B    
## 10   12. B    
## 11   13. A    
## 12   14. B    
## 13   15. A    
## 14   16. C    
## 15   17. B    
## 16   18. B

3.2 過濾(filter)

filter可以篩選符合條件的變數的觀察值,篩選的變數可以超過一個,例如:

tibble_pp0797b2.filter<-filter(tibble_pp0797b2, sex=="男性", TOWNID>6300)
tibble_pp0797b2.filter
## # A tibble: 130 x 24
##    Q1     Q2     Q3     Q4     Q5    Q6    Q7    Q8    Q9    Q10   partyid
##    <fct>  <fct>  <fct>  <fct>  <fct> <fct> <fct> <fct> <fct> <fct> <fct>  
##  1 非常不同意… 非常同意… 不同意 同意   很難說… 不同意… 不同意… 不相信… 不同意… 不同意… 中立及看情形…
##  2 非常不同意… 非常同意… 非常不同意… 非常同意… 同意  非常同意… 不同意… 不相信… 不同意… 不同意… 中立及看情形…
##  3 非常不同意… 同意   不同意 同意   非常同意… 非常同意… 同意  非常不相… 不同意… 同意  中立及看情形…
##  4 非常不同意… 很難說 很難說 很難說 不同意… 不同意… 同意  相信  同意  不同意… 民進黨 
##  5 非常同意… 非常同意… 不同意 同意   同意  同意  不同意… 非常不相… 非常不同… 非常不同… 國民黨 
##  6 不同意 同意   不同意 同意   同意  同意  同意  不相信… 不同意… 不同意… 國民黨 
##  7 同意   非常同意… 同意   非常同意… 不同意… 非常不同… 同意  不相信… 同意  非常不同… 民進黨 
##  8 同意   非常同意… 非常不同意… 同意   非常同意… 非常同意… 同意  非常不相… 非常不同… 不同意… 中立及看情形…
##  9 很難說 拒答   同意   拒答   同意  同意  不同意… 很難說… 很難說… 不同意… 中立及看情形…
## 10 同意   同意   不同意 不同意 非常同意… 同意  同意  不相信… 不同意… 同意  國民黨 
## # ... with 120 more rows, and 13 more variables: PARTY <fct>, tondu <fct>,
## #   ethnic <fct>, age <fct>, edu <fct>, sengiF <fct>, sengiM <fct>,
## #   CAREER <fct>, CAREER8 <fct>, TOWNID <dbl>, arear <fct>, sex <fct>,
## #   w <dbl>

可以看出,類別變數或者是數字變數都可以篩選觀察值。

3.3 創造新變數(mutate)

我們可以直接在資料中創造一個新變數,不需要再用錢字符號($),並且轉換資料型態,例如:

dt_mutate <- mutate(dt, S=as.factor(s), X=x*100)
dt_mutate <- mutate(dt_mutate, sn=as.numeric(S))
dt_mutate
## # A tibble: 16 x 7
##    s         x     y     z S         X    sn
##    <chr> <int> <dbl> <dbl> <fct> <dbl> <dbl>
##  1 B         1    1.    3. B      100.    2.
##  2 B         2    1.    4. B      200.    2.
##  3 A         3    1.    5. A      300.    1.
##  4 B         4    1.    6. B      400.    2.
##  5 A         5    1.    7. A      500.    1.
##  6 C         6    1.    8. C      600.    3.
##  7 B         7    1.    9. B      700.    2.
##  8 B         8    1.   10. B      800.    2.
##  9 B         9    1.   11. B      900.    2.
## 10 B        10    1.   12. B     1000.    2.
## 11 A        11    1.   13. A     1100.    1.
## 12 B        12    1.   14. B     1200.    2.
## 13 A        13    1.   15. A     1300.    1.
## 14 C        14    1.   16. C     1400.    3.
## 15 B        15    1.   17. B     1500.    2.
## 16 B        16    1.   18. B     1600.    2.

3.4 排序(arrange)

我們可以根據某一個或者一個以上的變數遞增或是遞減排序資料,例如:

dt_arrange = arrange(dt, s, desc(z))
dt_arrange
## # A tibble: 16 x 4
##    s         x     y     z
##    <chr> <int> <dbl> <dbl>
##  1 A        13    1.   15.
##  2 A        11    1.   13.
##  3 A         5    1.    7.
##  4 A         3    1.    5.
##  5 B        16    1.   18.
##  6 B        15    1.   17.
##  7 B        12    1.   14.
##  8 B        10    1.   12.
##  9 B         9    1.   11.
## 10 B         8    1.   10.
## 11 B         7    1.    9.
## 12 B         4    1.    6.
## 13 B         2    1.    4.
## 14 B         1    1.    3.
## 15 C        14    1.   16.
## 16 C         6    1.    8.

4 摘要式指令

4.1 摘要(summarize)

我們可以直接輸出某一個變數的統計結果:

summarize(dt, mean(x))
## # A tibble: 1 x 1
##   `mean(x)`
##       <dbl>
## 1      8.50

或者是轉成另一個變數,方便後續的分析,但是dplyr會存成一個tibble資料,所以需要再取出:

dt.sze=summarize(dt, x.avg=mean(x), z.avg=mean(z))
dt.sze[,1]
## # A tibble: 1 x 1
##   x.avg
##   <dbl>
## 1  8.50
dt.sze[,2]
## # A tibble: 1 x 1
##   z.avg
##   <dbl>
## 1  10.5

summarize可以計算的統計有:

  • mean,平均值
  • median,中位數
  • sum,總數
  • min,最小值
  • max,最大值
  • n(),個數,也就是資料筆數
  • n_distinct,類別的個數

(請見DSC2014tutorial)
例如我們想要知道mtcars這筆資料中cyl的個數、平均數跟類別的數目:

mtcars_n<-summarize(mtcars, n(), mean(cyl), n_distinct(cyl))

4.2 資料彙總(group_by)

我們可以根據資料內的類別變數對另一個變數進行統計,例如計算平均值,使用group_by()這個函數:

summarize(group_by(dt, s),  mean(z))
## # A tibble: 3 x 2
##   s     `mean(z)`
##   <chr>     <dbl>
## 1 A          10.0
## 2 B          10.4
## 3 C          12.0

如果資料內有遺漏值,可以設定na.rm這個參數為真,去除遺漏值,再進行統計,例如以flights這筆資料為例,根據tailnum也就是班機號碼,彙總計算班機次數以及距離:

library(nycflights13)
by_tailnum <- group_by(flights, tailnum)
delay <- summarise(by_tailnum,
  count = n(),
  dist = mean(distance, na.rm = TRUE))
delay
## # A tibble: 4,044 x 3
##    tailnum count  dist
##    <chr>   <int> <dbl>
##  1 D942DN      4  854.
##  2 N0EGMQ    371  676.
##  3 N10156    153  758.
##  4 N102UW     48  536.
##  5 N103US     46  535.
##  6 N104UW     47  535.
##  7 N10575    289  520.
##  8 N105UW     45  525.
##  9 N107US     41  529.
## 10 N108UW     60  534.
## # ... with 4,034 more rows

或者是(參考:https://dplyr.tidyverse.org/articles/dplyr.html ):

flights %>% group_by(tailnum) %>%
  summarize(count=n(), avgdist=mean(distance, na.rm=TRUE))
## # A tibble: 4,044 x 3
##    tailnum count avgdist
##    <chr>   <int>   <dbl>
##  1 D942DN      4    854.
##  2 N0EGMQ    371    676.
##  3 N10156    153    758.
##  4 N102UW     48    536.
##  5 N103US     46    535.
##  6 N104UW     47    535.
##  7 N10575    289    520.
##  8 N105UW     45    525.
##  9 N107US     41    529.
## 10 N108UW     60    534.
## # ... with 4,034 more rows

以上的說明希望大家活用dplyr,進行統計,並且結合資料視覺化。


5 資料的寬表與長表(reshape2)

dplyr提供了許多轉換資料以及彙總計算的功能,而針對資料的轉換,reshape2套件有很大的幫助。reshape2也是由 Hadley Wickham所寫,該套件裡最重要的兩個函數便是 melt() 與 dcast(),如同字面上的意思,melt 是熔化的意思,也就是將資料由多變數熔成較少變數且較長的資料,可以想像資料變長;cast 是鑄造的意思,也就是將資料由較少變數鑄造成較多變數且較寬的資料,可以想像資料變短。cast 有分 dcast 與 acast,只差在要輸出的形式是 data.frame 或是 array。(以上文字參考:https://blog.stranity.com.tw/2016/12/12/r語言reshape2套件/

5.1 寬表(dcast)

將資料由少變數變形為較寬的資料,在過程中可以加上函數。例如有一筆資料表示銀行的房貸金額,我們先讀取資料,過程中擷取年份與月份:

library(DSC2014Tutorial)
ETL_file("cl_info_other.csv")
## [1] "/Library/Frameworks/R.framework/Versions/3.4/Resources/library/DSC2014Tutorial/ETL/cl_info_other_unix.csv"
bank.info = read.table(file=ETL_file("cl_info_other.csv"),sep=",",stringsAsFactors=F,header=T)
bank.part=mutate(bank.info,
                 bank_code = as.factor(bank_code),
                 etl_dt = substr(etl_dt, 1, 7))

bank.part=mutate(bank.part, yearmonth=format(etl_dt, format='%Y-%m'))
    稍微選取變數方便觀察資料
bank.part<-select(bank.part, bank_nm, yearmonth, mortgage_bal)
head(bank.part)
##                    bank_nm yearmonth mortgage_bal
## 1         日商瑞穗實業銀行   2013-11   0.0000e+00
## 2 台北縣淡水第一信用合作社   2013-11   1.6873e+10
## 3             萬泰商業銀行   2013-11   5.6240e+09
## 4     台中市第二信用合作社   2013-11   1.8949e+10
## 5     基隆市第二信用合作社   2013-11   3.7730e+09
## 6       高雄第三信用合作社   2013-11   2.4760e+09
    (指令參考:DSC2014Tutorial套件的說明,請先安裝該套件,並且輸入slides(‘ETL1’)。如果有問題請參考授課大綱。)

然後就銀行名稱(bank_nm)以及年度月份(yearmonth)轉形為寬表,可顯示銀行名稱、每一個時間點的銀行貸款總額(為了顯示方便,銀行貸款一律除以10億):

library(reshape2)
bank.part$mortgage_bal.new=bank.part$mortgage_bal/10e+9
wtable<-dcast(bank.part, bank_nm ~ yearmonth,  value.var=c('mortgage_bal.new'), sum)
wtable
##                      bank_nm   2013-11  2013-12  2014-01  2014-04 2014-05
## 1               安泰商業銀行  455.8923  20.3757  15.2651  10.1400  5.0763
## 2               澳商澳盛銀行   39.6716   0.0000   4.7207   0.0000  0.0000
## 3         澳商澳洲紐西蘭銀行    0.0154   0.0000   0.0000   0.0000  0.0000
## 4                       澳盛    8.6770  12.9826   3.4501   7.1376  3.5712
## 5               板信商業銀行  330.0505  10.2763   8.2238   5.1035  2.5702
## 6               寶華商業銀行   52.4839   0.0000   0.0000   0.0000  0.0000
## 7     比利時商比利時聯合銀行    0.1566   0.0000   0.0000   0.0000  0.0000
## 8           比利時商富通銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 9             大陸商交通銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 10        大陸商中國建設銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 11            大陸商中國銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 12            大台北商業銀行   52.8824   3.0092   2.5724   0.0000  0.0000
## 13              大眾商業銀行  671.4575  37.2538  28.5782  18.7963  9.4068
## 14        淡水第一信用合作社   64.7933   9.7628   7.1920   5.1138  2.5813
## 15              稻江商業銀行   14.9729   0.0000   0.0000   0.0000  0.0000
## 16            德商德意志銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 17              第七商業銀行   12.9705   0.0000   0.0000   0.0000  0.0000
## 18              第一商業銀行 2164.1011 116.9979  86.9194  58.4418 29.2921
## 19          法國東方匯理銀行    0.0858   0.0000   0.0000   0.0000  0.0000
## 20              法國興業銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 21          法商法國巴黎銀行    0.6860   0.0024   0.0018   0.0012  0.0006
## 22              法商佳信銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 23            菲律賓首都銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 24              斐商標準銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 25        高雄第二信用合作社   17.3308   0.0000   0.0000   0.0000  0.0000
## 26        高雄第三信用合作社   55.6903   0.0000   0.0000   0.0000  0.0000
## 27      高雄市第三信用合作社   24.8881   2.8013   2.1591   1.6027  0.7962
## 28                  高雄銀行  292.3132  12.5998   9.2073   6.6557  3.3527
## 29          國泰世華商業銀行 2223.2194 102.0286  78.8050  51.0160 25.5519
## 30          合作金庫商業銀行 3767.5942 169.3300 134.3408  88.9293 44.6074
## 31              合作金庫銀行  111.2887   0.0000   0.0000   0.0000  0.0000
## 32            荷蘭商安智銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 33              荷商安銀銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 34        花蓮第二信用合作社  121.8997   4.8504   3.5344   2.4755  1.2451
## 35        花蓮第一信用合作社   61.0537   3.8185   2.7883   1.8716  0.9289
## 36                      花旗  390.1259  32.9079  24.3761  17.1927  8.5963
## 37              華南商業銀行 2576.4859 158.3480 118.3445  79.1740 39.6014
## 38              華泰商業銀行  120.0937   5.5938   3.9813   2.5195  1.2510
## 39        基隆第一信用合作社   23.5140   3.6329   2.6218   1.9136  0.9598
## 40      基隆市第二信用合作社   44.7062   3.0869   2.3235   1.7251  0.8534
## 41      基隆市第一信用合作社   42.0648   0.0000   0.0000   0.0000  0.0000
## 42          加拿大商豐業銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 43      嘉義巿第四信用合作社    1.0601   0.0000   0.0000   0.0000  0.0000
## 44      嘉義市第三信用合作社   15.8956   1.4514   1.0487   0.7396  0.3728
## 45              建華商業銀行  172.4026   0.0000   0.0000   0.0000  0.0000
## 46                  交通銀行   35.9057   0.0000   0.0000   0.0000  0.0000
## 47          金門縣信用合作社    3.1091   0.3467   0.2311   0.1838  0.0928
## 48              京城商業銀行  184.8479   6.1705   4.4346   3.3029  1.6557
## 49              聯邦商業銀行  562.6416  23.2065  17.1469  11.7545  5.8939
## 50              美國運通銀行    0.0005   0.0000   0.0000   0.0000  0.0000
## 51              美商道富銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 52              美商富國銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 53              美商花旗銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 54          美商加州聯合銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 55      美商美國紐約梅隆銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 56          美商美國紐約銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 57              美商美國銀行    0.0314   0.0000   0.0000   0.0000  0.0000
## 58              美商美聯銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 59          美商摩根大通銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 60      苗栗縣竹南信用合作社   21.3096   0.0000   0.0000   0.0000  0.0000
## 61        澎湖第二信用合作社    5.1287   0.8407   0.6071   0.4191  0.2132
## 62      澎湖縣第二信用合作社    5.7510   0.0000   0.0000   0.0000  0.0000
## 63      澎湖縣第一信用合作社    2.8879   0.1763   0.1185   0.0907  0.0455
## 64          日商瑞穗實業銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 65              日商瑞穗銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 66          日商三井住友銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 67      日商三菱東京日聯銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 68          日盛國際商業銀行  414.1284  16.4723  12.2290   8.4252  4.2223
## 69        瑞士商瑞士信貸銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 70            瑞士商瑞士銀行    0.6944   0.0424   0.0330   0.0212  0.0106
## 71              瑞興商業銀行    0.0000   1.0222   1.0179   2.0400  1.0211
## 72              三信商業銀行  156.5468   7.4360   5.5540   3.7230  1.8631
## 73          上海商業儲蓄銀行  854.4311  45.8736  34.0033  23.7441 11.8944
## 74              台北富邦銀行 2162.6112 112.9597  84.0778  57.5957 28.7917
## 75      台北市第九信用合作社   26.2689   2.5787   1.8887   1.2268  0.6156
## 76      台北市第五信用合作社   26.4813   1.6851   1.2204   0.8773  0.4431
## 77      台北市第一信用合作社   15.9363   0.0000   0.0000   0.0000  0.0000
## 78  台北縣淡水第一信用合作社  111.7306   0.0000   0.0000   0.0000  0.0000
## 79      台北縣淡水信用合作社   20.4316   0.4531   0.4405   0.0000  0.0000
## 80        台南第六信用合作社    0.0000   0.0000   0.0000   0.0000  0.0000
## 81        台南第三信用合作社   37.0272   2.8486   2.0862   1.4591  0.7347
## 82          台新國際商業銀行 1797.0183  86.2433  65.5713  43.9081 22.0041
## 83              台中商業銀行  225.6101  20.8217  14.8320  11.0376  5.5510
## 84      台中市第二信用合作社  137.3252   5.1242   3.7208   2.6652  1.3267
## 85        臺南區中小企業銀行   10.6257   0.0000   0.0000   0.0000  0.0000
## 86              臺灣工業銀行    0.0239   0.0000   0.0000   0.0000  0.0000
## 87              臺灣土地銀行 4726.7059 246.4167 184.5319 127.5156 64.0046
## 88          臺灣新光商業銀行  593.9176  40.1682  29.7785  21.0930 10.5613
## 89                  臺灣銀行 2738.6589 171.2308 123.4089  89.4212 44.7856
## 90          臺灣中小企業銀行 1245.4765  55.6679  41.1375  27.9560 14.0726
## 91              臺中商業銀行  168.1371   0.0000   0.0000   0.0000  0.0000
## 92              泰國盤谷銀行    0.0048   0.0000   0.0000   0.0000  0.0000
## 93            桃園信用合作社   21.6680   1.0406   0.6054   0.5628  0.2889
## 94              萬泰商業銀行   78.5559   9.5962   6.7137   4.8711  2.4440
## 95    西班牙商西班牙對外銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 96              香港東亞銀行    0.0096   0.0000   0.0000   0.0000  0.0000
## 97          香港上海匯豐銀行  338.4479   0.0000   0.0000   0.0000  0.0000
## 98      新北市淡水信用合作社    0.0000   0.4412   0.2242   0.4570  0.2283
## 99            新加坡大華銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 100   新加坡商新加坡華僑銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 101         新加坡商星展銀行   76.7716   0.0000   0.0000   0.0000  0.0000
## 102       新竹第三信用合作社   17.5981   2.8885   2.0264   1.4001  0.7017
## 103       新竹第一信用合作社   28.7734   4.8625   3.6611   2.5519  1.3054
## 104         新竹國際商業銀行  163.9289   0.0000   0.0000   0.0000  0.0000
## 105     新竹市第三信用合作社   30.3709   0.0000   0.0000   0.0000  0.0000
## 106     新竹市第一信用合作社   47.3216   0.0000   0.0000   0.0000  0.0000
## 107                     星展   54.7337  16.3461  11.4036   8.4414  4.2310
## 108             陽信商業銀行  434.9034  16.7865  12.8226   7.9943  4.0000
## 109             宜蘭信用合社   10.0521   0.0000   0.1415   0.0000  0.0000
## 110           宜蘭信用合作社    0.9360   0.8064   0.3497   0.4507  0.2309
## 111           英商巴克萊銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 112             英商渣打銀行   16.4841   0.0000   0.0000   0.0000  0.0000
## 113             永豐商業銀行 2068.4916  90.6752  67.6777  44.2109 22.0346
## 114             玉山商業銀行 1514.4453  83.4300  61.3086  40.9703 20.4765
## 115             元大商業銀行  449.6893  35.2202  24.8519  18.1559  9.1095
## 116         遠東國際商業銀行  820.8375  44.3036  32.6891  21.8612 10.9321
## 117         渣打國際商業銀行  990.2054  64.2683  47.9260  32.0244 16.1259
## 118       彰化第六信用合作社   49.2319   2.9499   2.1565   1.5759  0.7850
## 119       彰化第十信用合作社   12.1791   1.1159   0.7626   0.5754  0.2882
## 120       彰化第五信用合作社    8.0686   0.6685   0.4041   0.3725  0.1880
## 121       彰化第一信用合作社   13.5215   1.2920   0.9367   0.6600  0.3250
## 122             彰化商業銀行 1526.2329  94.9249  72.1288  48.6897 24.3888
## 123     彰化縣鹿港信用合作社   26.2948   2.4027   1.7475   1.2220  0.6130
## 124         兆豐國際商業銀行 1368.9686  74.8504  52.3233  41.5007 20.8362
## 125         中國國際商業銀行   57.8369   0.0000   0.0000   0.0000  0.0000
## 126           中國輸出入銀行    0.0000   0.0000   0.0000   0.0000  0.0000
## 127         中國信託商業銀行 2483.0095 126.2968  90.6653  65.1645 32.7264
## 128         中華開發工業銀行    0.0338   0.0000   0.0000   0.0000  0.0000
## 129           竹南信用合作社    2.4617   0.0000   0.0000   0.0000  0.0000

sum可以替代為length()以及mean()。雖然寬表提供一些統計功能,也方便我們閱讀,但是無法視覺化寬表的資料。所以我們用melt轉形資料。

5.2 長表(melt)

長表無法彙總資料,但是可以轉置資料,讓每一筆資料對應一個觀察值,而不是對應超過一個觀察值。我們先用上述的寬表,轉置為長表:

colnames(wtable)<-c("bank_nm","time1","time2","time3","time4","time5")
bank.melt=melt(wtable, id.vars=c('bank_nm'))

接下來用ggplot2進行視覺化,目標是顯示每一個銀行在五個時間點的貸款總額變化:

library(ggplot2)
#complete
p=ggplot(bank.melt, aes(x=variable, y=value, group=bank_nm, color=bank_nm)) +
  geom_line(stat="identity") +
  theme(axis.text.x=element_text(family="msjh", size=10)) +
  scale_x_discrete(labels = c("2013-11", "2013-12", "2014-01", "2014-04", "2014-05")) +
    theme_bw()

因為原始資料之中有100多家銀行在五個時間點的資料,為了容易觀察起見,我們只繪圖三家銀行,首先隨機抽出三家銀行:

#-------------------------------------------------
#partial: 3 banks
set.seed(02139)
bankname<-unique(bank.melt$bank_nm)
r<-sample(c(1:length(bankname)), size=3, replace=F)
bankname.r <- bankname[r]
bankname.r
## [1] "大台北商業銀行"     "大陸商交通銀行"     "新竹第三信用合作社"

接下來畫圖:

bank.r<-bank.melt[which(bank.melt$bank_nm==bankname.r[1]|
                          bank.melt$bank_nm==bankname.r[2]|
                          bank.melt$bank_nm==bankname.r[3]),]
p=ggplot(bank.r, aes(x=variable, y=value, group=bank_nm, color=bank_nm)) +
  geom_line(stat="identity") +
  theme(legend.text=element_text(family="微軟正黑體", size=10)) +
  scale_x_discrete(labels = c("2013-11", "2013-12", "2014-01", "2014-04", "2014-05")) +
    theme_bw()
p
    可以看出有的銀行一開始貸款總額相當大,然後突然下降,有的則是一直缺少房貸。

接下來我們看另一個範例。還記得介紹迴圈時所示範的清理主計處數據:

library(foreign)
stat.dat<-read.csv("CS3171D1A.csv",header=TRUE,sep=";",dec=".",fileEncoding="BIG5")

我們將要多擷取兩個年度的老年人口比率資料,以及擷取三個年度的失業率資料,對每一項資料我們需要一個迴圈,每一個迴圈裡面有兩個變數,也就是從哪一列跟哪一行開始讀取資料:

tempold<-data.frame()
      for (i in 1:3){
       for (u in 1:23){    
         tempold[u,i]<-stat.dat[i+1, u+1]
 }
   print(i)
      }
## [1] 1
## [1] 2
## [1] 3
tempunemploy<-data.frame()
      for (i in 1:3){
       for (u in 1:23){    
         tempunemploy[u,i]<-stat.dat[i+13, u+1]
 }
   print(i)
      }
## [1] 1
## [1] 2
## [1] 3

結合成為資料框,但是用tibble格式觀察資料:

countyname<-colnames(stat.dat)[-1]
temp.df <- data.frame(countyname, tempold, tempunemploy)
temp.df.t <-as_tibble(temp.df); temp.df.t
## # A tibble: 23 x 7
##    countyname    V1    V2    V3  V1.1  V2.1  V3.1
##  * <fct>      <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1 臺北縣      6.37  6.44  6.55  3.00  4.90  5.50
##  2 宜蘭縣     10.2  10.5  10.8   3.60  5.00  5.40
##  3 桃園縣      7.46  7.49  7.51  2.00  4.30  5.10
##  4 新竹縣      9.69  9.91 10.2   1.70  3.80  4.40
##  5 苗栗縣     11.0  11.2  11.6   2.70  4.50  4.90
##  6 臺中縣      7.16  7.32  7.50  3.50  5.00  5.40
##  7 彰化縣      9.42  9.73 10.0   1.70  4.00  5.20
##  8 南投縣     10.6  10.9  11.2   3.80  4.90  5.30
##  9 雲林縣     11.6  12.0  12.4   2.60  4.10  4.70
## 10 嘉義縣     12.4  12.8  13.1   2.80  4.00  5.20
## # ... with 13 more rows

在這個資料框中,V1代表2000年的老年人口,所以它有

  1. 年代
  2. 老年人口

這兩個性質,而V1.1代表2000年的失業率,也是有兩個性質,為了區隔這兩個特性,我們再結合一次,這次把失業率放在老年人口比率底下:

info <- rep('old', 23)
temp.df1<-cbind(countyname, info, tempold)
info <- rep('unemploy', 23)
temp.df2<-cbind(countyname, info, tempunemploy)
temp.df<-data.frame(rbind(temp.df1, temp.df2))

接下來用melt指令轉置資料,並且把其中的年度資料轉換為字串資料,以方便後面的分析:

new.df<-melt(temp.df, id=c('countyname', 'info'), 
             variable.name=c("Time"),
measure.vars = c("V1","V2","V3"))
new.df$Year<-c()
new.df$Year[new.df$Time=='V1']<-2000
new.df$Year[new.df$Time=='V2']<-2001
new.df$Year[new.df$Time=='V3']<-2002
new.df$Year<-as.character(new.df$Year)

如果以縣市為單位,而歸納這三年的兩個變數分別的總和,可以用以下的程式畫圖:

g1<-ggplot(new.df, aes(x=countyname, y=value, fill=info)) +
  geom_bar(stat='identity') +
  theme(axis.text.x=element_text(family="HanWangMingBold", size=10))
g1

如果以縣市為單位,而歸納這兩個變數的每一年總和,可以用以下的程式畫圖:

g2<-ggplot(new.df, aes(x=countyname, y=value, fill=Year)) +
  geom_bar(stat='identity') +
  theme(axis.text.x=element_text(family="微軟正黑體", size=10))
g2

以上兩種統計方式都是以縣市為單位,而選擇年度(三個類別)或者是統計資料(兩個類別)做為歸納單位,但是有沒有可能同時統計這兩者?也就是每一個縣市、每一個年度、老年人口比率與失業率的數字?

g3<-ggplot(new.df, aes(x=countyname, y=value, fill=info)) +
  geom_bar(stat='identity') +
  facet_wrap( ~ Year) +
  theme(axis.text.x=element_text(family="HanWangMingBold", size=6))
g3

以上程式使用facet_wrap()納入第二個類別變數,繪出三個直方圖,分別代表三個年度的兩個變數的比率。
以上說明寬表、長表的用途,希望能有助於資料轉置以及後續分析。


6 作業

    1. 請下載nycflights13這個套件,然後分析flights這筆資料,並且建立新變數「速度」,公式為距離(distance)除以飛行時間(air_time)乘以60。請問平均速度多少?最高速多少?可以用filter篩選沒有遺漏值的觀察值,例如:
tibble1<-tibble(A=c(NA, NA, NA, 100, 200, 600, NA, 100, 0, 200),
                B=200,
                C=c(rep(300, 5), rep(400, 5)))
tibble1 = filter(tibble1, !is.na(A))
       summarize(tibble1, sum(A,B,C), mean(C))
## # A tibble: 1 x 2
##   `sum(A, B, C)` `mean(C)`
##            <dbl>     <dbl>
## 1          4600.      367.
    1. 請讀取studentsfull.txt這個檔案,然後計算不同科系同學的平均分數,再根據平均分數排序資料表:
    1. 請統計mtcars這筆資料中cyl的各類的平均馬力(hp) 以及每加侖可以行駛的英里數(mpg):
    1. 請統計flights資料中每年的最後一天的平均出發以及抵達的遲到分鐘
    1. 請從bank.info資料挑出other_cl_bal大於100億的銀行資料,並且列出銀行的名稱。