1 課程目標

  • Rdplyr的套件中的指令,包括selectfiltermutate等函數,協助研究者整理資料,並且轉置資料。例如:
library(dplyr)
file <- here::here('data', 'studentsfull.txt')
students<-read.table(file, 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  NA
## 2  10325023    Becky    Physics    86      F  NA
## 3  10430101     Carl Journalism    69      M  NA
## 4  10401032  Dimitri    English    83      M  NA
## 5  10307120  Enrique  Chemistry    80      M  NA
## 6  10207005 Fernando  Chemistry    66      M  NA
## 7  10305019   George  Mechanics    75      F  NA
## 8  10305022   Howell  Mechanics    81      M  NA
## 9  10305029      Ian  Mechanics    60      M  NA
## 10 10305031    Julio  Mechanics    89      M  NA
## 11 10322014    Kaori  Aerospace    82      F  NA
## 12 10425026     Luke    Physics    88      M  NA
## 13 10401022   Miguel    English    92      M  NA
## 14 10501006      Neo    English    77      M  NA
## 15 10321010   Olivia  Economics    85      F  NA
## 16 10321011    Peter  Economics    88      M  NA
## 17 10405017     Qing  Mechanics    88      F  NA
## 18 10422007    Ricky  Aerospace    91      M  NA
## 19 10422008    Seiko  Aerospace    80      F  NA
## 20 10430005  Terresa Journalism    62      F  NA
## 21 10530009     Usla Journalism    87      F  NA
## 22 10421001   Vivian  Economics    70      F  NA
## 23 10307018    Wendy  Chemistry    85      F  NA
## 24 10425003     Xing    Physics    93      M  NA
## 25 10221030     Yoko  Economics    66      F  NA
## 26 10430015      Zoe Journalism    92      F  NA

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 × 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 × 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)
file <- here::here('data', 'PP0797B2.sav')
pp0797b2<-read.spss(file, to.data.frame=TRUE)
tibble_pp0797b2<-as_tibble(pp0797b2)
head(tibble_pp0797b2)
## # A tibble: 6 × 24
##   Q1         Q2    Q3    Q4    Q5    Q6    Q7    Q8    Q9    Q10   partyid PARTY
##   <fct>      <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>   <fct>
## 1 很難說     同意  不同… 同意  同意  不同… 同意  不相… 不同… 不同… 國民黨  偏國…
## 2 非常不同意 非常… 不同… 同意  很難… 不同… 不同… 不相… 不同… 不同… 中立及… 中立…
## 3 非常不同意 非常… 非常… 非常… 同意  非常… 不同… 不相… 不同… 不同… 中立及… 中立…
## 4 同意       同意  不同… 同意  不同… 非常… 不同… 很難… 不同… 非常… 民進黨  普通…
## 5 非常不同意 同意  不同… 不同… 不同… 不同… 同意  不相… 同意  非常… 國民黨  非常…
## 6 不同意     不同… 同意  同意  同意  同意  同意  不相… 不同… 非常… 中立及… 中立…
## # ℹ 12 more variables: 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 × 24
##   Q1         Q2    Q3    Q4    Q5    Q6    Q7    Q8    Q9    Q10   partyid PARTY
##   <fct>      <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>   <fct>
## 1 很難說     同意  不同… 同意  同意  不同… 同意  不相… 不同… 不同… 國民黨  偏國…
## 2 非常不同意 非常… 不同… 同意  很難… 不同… 不同… 不相… 不同… 不同… 中立及… 中立…
## 3 非常不同意 非常… 非常… 非常… 同意  非常… 不同… 不相… 不同… 不同… 中立及… 中立…
## 4 同意       同意  不同… 同意  不同… 非常… 不同… 很難… 不同… 非常… 民進黨  普通…
## 5 非常不同意 同意  不同… 不同… 不同… 不同… 同意  不相… 同意  非常… 國民黨  非常…
##   tondu ethnic age   edu   sengiF sengiM CAREER CAREER8 TOWNID arear sex       w
##   <fct> <fct>  <fct> <fct> <fct>  <fct>  <fct>  <fct>    <dbl> <fct> <fct> <dbl>
## 1 維持… 都是   50至… 專科  本省…  本省…  高、…  軍公教…   1404 宜花… 男性  0.556
## 2 維持… 台灣人 60歲… 大學… 本省…  本省…  高、…  軍公教…   6306 大台… 男性  0.779
## 3 永遠… 都是   30至… 高中… 本省…  本省…  藍領   私部門…   6410 高屏… 男性  1.30 
## 4 維持… 台灣人 30至… 高中… 本省…  本省…  高、…  私部門…    101 大台… 男性  1.52 
## 5 維持… 都是   30至… 大學… 本省…  本省…  中低…  私部門…    904 雲嘉… 男性  0.626
## # ℹ 2,053 more rows
  • 而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 × 2
##   sex       n
##   <fct> <dbl>
## 1 男性  1031.
## 2 女性  1027.
  • Hadley Wickham也是ggplot2的作者,因此tibble資料適合於ggplot2的視覺化,例如我們想呈現性別的分佈,不一定用得到tibble:
library(ggplot2)
showtext::showtext_auto()
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 × 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 畫直方圖:
showtext::showtext_auto()
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 × 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 × 24
##    Q1        Q2    Q3    Q4    Q5    Q6    Q7    Q8    Q9    Q10   partyid PARTY
##    <fct>     <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>   <fct>
##  1 非常不同… 非常… 不同… 同意  很難… 不同… 不同… 不相… 不同… 不同… 中立及… 中立…
##  2 非常不同… 非常… 非常… 非常… 同意  非常… 不同… 不相… 不同… 不同… 中立及… 中立…
##  3 非常不同… 同意  不同… 同意  非常… 非常… 同意  非常… 不同… 同意  中立及… 中立…
##  4 非常不同… 很難… 很難… 很難… 不同… 不同… 同意  相信  同意  不同… 民進黨  非常…
##  5 非常同意  非常… 不同… 同意  同意  同意  不同… 非常… 非常… 非常… 國民黨  非常…
##  6 不同意    同意  不同… 同意  同意  同意  同意  不相… 不同… 不同… 國民黨  普通…
##  7 同意      非常… 同意  非常… 不同… 非常… 同意  不相… 同意  非常… 民進黨  非常…
##  8 同意      非常… 非常… 同意  非常… 非常… 同意  非常… 非常… 不同… 中立及… 中立…
##  9 很難說    拒答  同意  拒答  同意  同意  不同… 很難… 很難… 不同… 中立及… 中立…
## 10 同意      同意  不同… 不同… 非常… 同意  同意  不相… 不同… 同意  國民黨  普通…
## # ℹ 120 more rows
## # ℹ 12 more variables: 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 × 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
  • 我們可以利用mutate改變變數的性質,例如把變數改成數字類型以及重新歸類因素類型的變數:
pp.tmp <- pp0797b2 %>% mutate(sex.n = as.numeric(sex)) %>% 
     mutate(Taiwanese = dplyr::recode_factor(ethnic, 
                台灣人='台灣人', 都是 = '雙重認同',
                中國人 = '雙重認同', .default = NA_character_))
pp.sex <- pp.tmp %>% janitor::tabyl(sex.n) %>% 
     janitor::adorn_totals()
pp.Taiwanese <- pp.tmp %>% janitor::tabyl(Taiwanese) %>% 
     janitor::adorn_totals()

3.4 排序(arrange)

  • 我們可以根據某一個或者一個以上的變數遞增或是遞減排序資料,例如:
dt_arrange = arrange(dt, s, desc(z))
dt_arrange
## # A tibble: 16 × 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)

  • 我們可以直接輸出某一個變數的統計結果:
summarise(dt, mean(x))
## # A tibble: 1 × 1
##   `mean(x)`
##       <dbl>
## 1       8.5
  • 或者是轉成另一個變數,方便後續的分析,但是dplyr會存成一個tibble資料,所以需要再取出:
dt.sze=summarise(dt, x.avg=mean(x), z.avg=mean(z))
dt.sze[,1]
## # A tibble: 1 × 1
##   x.avg
##   <dbl>
## 1   8.5
dt.sze[,2]
## # A tibble: 1 × 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 × 2
##   s     `mean(z)`
##   <chr>     <dbl>
## 1 A          10  
## 2 B          10.4
## 3 C          12
  • 如果資料內有遺漏值,可以設定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 × 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.
## # ℹ 4,034 more rows
flights %>% group_by(tailnum) %>%
  summarize(count=n(), avgdist=mean(distance, na.rm=TRUE))
## # A tibble: 4,044 × 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.
## # ℹ 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)
tmp <- ETL_file("cl_info_other.csv")
bank.info = read.table(tmp,
             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[1:6, ]
##            bank_nm   2013-11  2013-12 2014-01 2014-04 2014-05
## 1     三信商業銀行  156.5468   7.4360  5.5540  3.7230  1.8631
## 2 上海商業儲蓄銀行  854.4311  45.8736 34.0033 23.7441 11.8944
## 3 中國信託商業銀行 2483.0095 126.2968 90.6653 65.1645 32.7264
## 4 中國國際商業銀行   57.8369   0.0000  0.0000  0.0000  0.0000
## 5   中國輸出入銀行    0.0000   0.0000  0.0000  0.0000  0.0000
## 6 中華開發工業銀行    0.0338   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'))
# For example, renaming "variable" to "new_variable" and "value" to "new_value"
  • 接下來用ggplot2進行視覺化,目標是顯示每一個銀行在五個時間點的貸款總額變化:
library(ggplot2)
names(bank.melt)[names(bank.melt) == "Variable"] <- "Date"
#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() +
  labs(x = "Date")
  • 因為原始資料之中有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() +
    labs(x = "Date")
p 

  • 可以看出有的銀行一開始貸款總額相當大,然後突然下降,有的則是一直缺少房貸。

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

library(foreign)
DAT <- here::here("data", "CS3171D1A.csv")
stat.dat <-read.csv(DAT, 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 × 7
##    countyname    V1    V2    V3  V1.1  V2.1  V3.1
##    <chr>      <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1 臺北縣      6.37  6.44  6.55   3     4.9   5.5
##  2 宜蘭縣     10.2  10.5  10.8    3.6   5     5.4
##  3 桃園縣      7.46  7.49  7.51   2     4.3   5.1
##  4 新竹縣      9.69  9.91 10.2    1.7   3.8   4.4
##  5 苗栗縣     11.0  11.2  11.6    2.7   4.5   4.9
##  6 臺中縣      7.16  7.32  7.5    3.5   5     5.4
##  7 彰化縣      9.42  9.73 10.0    1.7   4     5.2
##  8 南投縣     10.6  10.9  11.2    3.8   4.9   5.3
##  9 雲林縣     11.6  12.0  12.4    2.6   4.1   4.7
## 10 嘉義縣     12.4  12.8  13.1    2.8   4     5.2
## # ℹ 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)) + coord_flip()
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 + coord_flip()

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

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

6 作業

  1. 請用group_by,summarise,mutate這些指令,計算pscl::AustralianElectionPolling裡面每個民調公司(org)的民調平均。

  2. 請計算africa2023.csv裡面,每個國家的人口數佔全非洲的比例,並且列出前五名的國家。

  3. 請計算ISLR裡面Wage這筆資料中,在2003年每一種工作類型(jobclass)以及每一個種族(race)的22歲的勞工平均薪資。

4.用mutateUsingR::BushApproval裡面的approval改成高於50或者低於50,民調單位(who)歸類為媒體與非媒體兩類。

  1. 請用readr::read_delim(file, delim = ';', show_col_type = F)這個語法讀取gktable.txt這筆資料,並且轉為長表。

  2. 請下載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<- tibble1 %>%  filter(!is.na(A)) %>% 
       summarise(sum(A,B,C), mean(C))
  1. 請讀取studentsfull.txt這個檔案,然後計算不同科系同學的平均分數,再根據平均分數排序資料表。

  2. 請統計mtcars這筆資料中cyl的各類的平均馬力(hp) 以及每加侖可以行駛的英里數(mpg):

  3. 請統計flights資料中每年的最後一天的平均出發以及抵達的遲到分鐘。

  4. 請從bank.info資料挑出other_cl_bal大於100億的銀行資料,並且列出銀行的名稱。

7 更新內容日期

## 最後更新日期 04/15/2024