4. 控制流程


4.1 條件判斷


4.1.1 if-else敘述

表達方式:if(A){B} else{C} ,代表若條件判斷句(A)為真,執行B,若不為真,則執行C。


以下以成績為例說明。

score<-50
if(score>=60){
  print("及格")
}else{
  print("不及格")
}
## [1] "不及格"
score<-70
if(score>=60){
  print("及格")
}else{
  print("不及格")
}
## [1] "及格"


4.1.2 if-else if-else

表達方式:if(A){B} else if(C){D}else{E} ,代表若條件判斷句(A)為真,執行B,若不為真,則再判斷條件句C是否為真,若為真,則執行D,若不為真,則執行E。

score<-98
if(score>=90){
  print("讚")
}else if(score>=60){
  print("及格")
}else{
  print("不及格")
}
## [1] "讚"


請比較下列兩個條件判斷有何差異。

#case 1
score<-50
if(score>=60){
  print("及格")
}else{
  print("不及格")
}
## [1] "不及格"
#case 2
score<-50
if(score>=60){
  print("及格")
}else if(score<60){
  print("不及格")
}
## [1] "不及格"


4.1.3 巢狀條件式


有時候必須判斷的條件太多,若剛好有些相似的點,可以利用類似階層式的寫法。

score<-78
if(score>=60){
  if(score>=90){
    print("讚")
  }else{
    print("及格")
  }
}else{
  print("不及格")
}
## [1] "及格"


4.1.4 ifelse()


ifelse()函數可用最短的方式取代if-else敘述。


表達方式:ifelse(A,B,C),若條件判斷式A為真,執行B,若不為真,則執行C。


ifelse()也可以支援向量。

score<-70
ifelse(score>=60,"及格","不及格")
## [1] "及格"
score<-c(30,70,80,56,99)
ifelse(score>=60,"及格","不及格")
## [1] "不及格" "及格"   "及格"   "不及格" "及格"


挑戰一下:102級貓空大學歷史系學測的面試門檻是,國文14級分,英文13級分,社會15級分,然大考中心規定,不能有任何一科是0級分。


請寫出一個if條件判斷式,判斷學生是否通過面試門檻。

#分數排序:國英數自社
score<-c(14,13,14,13,15)
if(sum(score>0)==5){
  if(score[1]>=14 && score[2]>=13 && score[5]==15){
    print("面試")
  }else{
    print("抱歉")
  }
}else{
  print("抱歉")
}
## [1] "面試"


4.2 迴圈


4.1.1 for迴圈

for(i in 1:5){
  print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5


也可以放入不連續的數字或字元

score<-c(50,78,90,54,67)
for(i in score){
  print(i)
}
## [1] 50
## [1] 78
## [1] 90
## [1] 54
## [1] 67
student<-c("a","b","c","d")
for(i in student){
  print(i)
}
## [1] "a"
## [1] "b"
## [1] "c"
## [1] "d"


4.1.1 while迴圈

x<-0
while(x<5){
  print(x)
  x<-x+1
}
## [1] 0
## [1] 1
## [1] 2
## [1] 3
## [1] 4


4.1.1 break

x<-0
while(x<5){
  print(x)
  x<-x+1
  if(x==3){
    break
  }
}
## [1] 0
## [1] 1
## [1] 2


5. 定義函數

pass_or_not<-function(x=score){
  if(x>=60){
    print("及格")
  }else{
    print("不及格")
  }
}
pass_or_not(x = 60)
## [1] "及格"
#fix(pass_or_not)


6. 資料整理


我們拿到的資料常常不是我們像要的樣子,因此第一步就是整理資料。


以下以台灣死亡率為例。


6.1 匯入資料

setwd("C:/Users/User/Google 雲端硬碟/政治大學ECO/R")
ppp106<-read.csv("106popu.csv")
data106<-read.table("opendata106.txt",header = T,sep = ",")


6.2 合併資料


6.2.1 rbind

m1<-matrix(data = 1:12,nrow = 3,ncol = 4)
m1
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
m2<-matrix(data = 13:24,nrow = 3,ncol = 4)
m2
##      [,1] [,2] [,3] [,4]
## [1,]   13   16   19   22
## [2,]   14   17   20   23
## [3,]   15   18   21   24
m3<-rbind(m1,m2)
m3
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
## [4,]   13   16   19   22
## [5,]   14   17   20   23
## [6,]   15   18   21   24


6.2.2 cbind

m4<-cbind(m1,m2)
m4
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,]    1    4    7   10   13   16   19   22
## [2,]    2    5    8   11   14   17   20   23
## [3,]    3    6    9   12   15   18   21   24


回到資料上,我們有101年至106年的人口資料,要如何合併?

setwd("C:/Users/User/Google 雲端硬碟/政治大學ECO/R")
ppp106<-read.csv("106popu.csv")
ppp105<-read.csv("105popu.csv")
ppp104<-read.csv("104popu.csv")
ppp103<-read.csv("103popu.csv")
ppp102<-read.csv("102popu.csv")
ppp101<-read.csv("101popu.csv")
ppp<-rbind(ppp106,ppp105,ppp104,ppp103,ppp102,ppp101)
rm(ppp101)
rm(ppp102)
rm(ppp103)
rm(ppp104)
rm(ppp105)
rm(ppp106)
print(ppp[c(1:10),])
##    year          county sex    a1    a2    a3     a4     a5     a6     a7
## 1  2017 New Taipei City   1 83113 86328 89407 115462 140403 145401 144569
## 2  2017 New Taipei City   2 77781 79690 81836 106618 129945 134646 144099
## 3  2017     Taipei City   1 73288 60065 58421  67866  76821  78398  88852
## 4  2017     Taipei City   2 69046 55825 53227  62497  72588  77173  99488
## 5  2017    Taoyuan City   1 58886 55129 58904  72591  82146  81747  83892
## 6  2017    Taoyuan City   2 54298 51295 53137  66398  76052  76732  84319
## 7  2017   Taichung City   1 71288 68972 71514  90306 105567 103767 105340
## 8  2017   Taichung City   2 65803 63759 66131  83708  98133  97883 105998
## 9  2017     Tainan City   1 39399 39852 42195  53864  64900  67117  69874
## 10 2017     Tainan City   2 36783 36855 38607  49274  60557  62089  68049
##        a8     a9    a10    a11    a12    a13    a14   a15   a16   a17
## 1  173568 160654 152201 151659 148874 131758  99398 50872 35790 20581
## 2  180232 168515 163597 171283 170212 152441 114137 58696 46327 28540
## 3  112036  98779  93412  93512  93459  90040  75160 42102 32045 20600
## 4  127012 112954 109323 108152 107829 104018  88535 51085 43347 29572
## 5   99141  88299  83665  81181  73487  60479  43693 22605 16932 10759
## 6  102867  90885  87187  84840  77799  66657  50026 27025 22408 14285
## 7  122222 106116 102072 101924  95842  81416  60125 31449 24962 15460
## 8  127195 114403 112318 111835 104033  88944  66212 36876 31638 21015
## 9   82598  72804  70172  74786  75432  64785  48238 25559 22094 15448
## 10  81864  74184  72357  75918  75790  65102  50230 29287 27700 21321
##      a18  a19  a20 a21
## 1  14822 6509 1710 318
## 2  15823 6812 1787 275
## 3  16509 7968 2205 379
## 4  18537 8486 2260 386
## 5  10839 4328  776 140
## 6   7956 3270  840 122
## 7  10583 4270  790 100
## 8  11611 4310 1019 161
## 9   9311 3204  567  79
## 10 12551 4555 1034 137


以同樣的手法處理死亡資料

setwd("C:/Users/User/Google 雲端硬碟/政治大學ECO/R")
data106<-read.table("opendata106.txt",header = T,sep = ",")
data105<-read.table("opendata105.txt",header = T,sep = ",")
data104<-read.table("opendata104.txt",header = T,sep = ",")
data103<-read.table("opendata103.txt",header = T,sep = ",")
data102<-read.table("opendata102.txt",header = T,sep = ",")
data101<-read.table("opendata101.txt",header = T,sep = ",")
data<-rbind(data106,data105,data104,data103,data102,data101)
rm(data101)
rm(data102)
rm(data103)
rm(data104)
rm(data105)
rm(data106)
print(data[c(1:10),])
##    year county cause sex age_code N
## 1   106      1     1   1       14 1
## 2   106      1     1   1       17 1
## 3   106      1     1   1       22 2
## 4   106      1     1   1       26 1
## 5   106      1     1   2       16 1
## 6   106      1     1   2       20 2
## 7   106      1     1   2       22 2
## 8   106      1     1   2       23 1
## 9   106      1     1   2       24 2
## 10  106      1     2   1       13 1


6.3 資料拉皮


我們發現人口資料的型態是wide format,不容易分析。


利用melt將wide format轉成long format

library(reshape2)
x<-data.frame(student=c("a","b","c"),math=c(80,76,98),eng=c(90,54,95),society=c(40,99,67))
x2<-melt(data = x,id.vars = "student",var="subject")
x2
##   student subject value
## 1       a    math    80
## 2       b    math    76
## 3       c    math    98
## 4       a     eng    90
## 5       b     eng    54
## 6       c     eng    95
## 7       a society    40
## 8       b society    99
## 9       c society    67


回到人口資料上。

pop2<- melt(ppp, id.vars=c('year','county', 'sex'),var='age')
pop2$age<-rep(1:21,each=264)
colnames(pop2)[5]<-"pop"


6.3 資料調整


兩份資料一定會有部分資料表現的形式不同,為了分析方便,故必須調整。


將死亡資料變數重新命名,並將表示形式調整成與人口資料相同。

colnames(data)[5]<-"age"
data[data[,5]<7,5]<-1
data[data[,5]>6,5]<-data[data[,5]>6,5]-5
summary(data$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    1.00   11.00   14.00   13.76   17.00   21.00
data[,1]<-data[,1]+1911


將縣市代號替換成縣市名稱。

data1<-data  
data1[data[,2]==1,2]<-"Taipei City"
data1[data[,2]==3,2]<-"Taichung City"
data1[data[,2]==5,2]<-"Tainan City"
data1[data[,2]==7,2]<-"Kaohsiung City"
data1[data[,2]==11,2]<-"Keelung City"
data1[data[,2]==12,2]<-"Hsinchu City"
data1[data[,2]==22,2]<-"Chiayi City"
data1[data[,2]==31,2]<-"New Taipei City"
data1[data[,2]==32,2]<-"Taoyuan City"
data1[data[,2]==33,2]<-"Hsinchu County"
data1[data[,2]==34,2]<-"Yilan County"
data1[data[,2]==35,2]<-"Miaoli County"
data1[data[,2]==37,2]<-"Changhua County"
data1[data[,2]==38,2]<-"Nantou County"
data1[data[,2]==39,2]<-"Yunlin County"
data1[data[,2]==40,2]<-"Chiayi County"
data1[data[,2]==43,2]<-"Pingtung County"
data1[data[,2]==44,2]<-"Penghu County"
data1[data[,2]==45,2]<-"Hualien County"
data1[data[,2]==46,2]<-"Taitung County"
data1[data[,2]==90,2]<-"Kinmen County"
data1[data[,2]==91,2]<-"Lienchiang County"
data<-data1
rm(data1)
#這部分之後才會提到,先忽略。
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
data2<-data %>% 
  group_by(year,county,sex,age,cause) %>% 
  summarise(num=sum(N))


新增一個data frame 並將死因變數納入人口資料中。

pop3<-data.frame(year=rep(pop2$year,each=135),
                 county=rep(pop2$county,each=135),
                 sex=rep(pop2$sex,each=135),
                 age=rep(pop2$age,each=135),
                 pop=rep(pop2$pop,each=135),
                 cause=rep(1:135,time=5544))


6.4 資料對照整併


將人口資料與死亡資料整併


利用 merge 整併

x<-data.frame(student=c("a","b","c","d"),height=c(160,156,178,172))
x
##   student height
## 1       a    160
## 2       b    156
## 3       c    178
## 4       d    172
y<-data.frame(student=c("a","b","d","e"),weight=c(53,42,70,76))
y
##   student weight
## 1       a     53
## 2       b     42
## 3       d     70
## 4       e     76
xy1<-merge(x = x,y = y,by = "student")
xy1
##   student height weight
## 1       a    160     53
## 2       b    156     42
## 3       d    172     70
xy2<-merge(x = x,y = y,by = "student",all = T)
xy2
##   student height weight
## 1       a    160     53
## 2       b    156     42
## 3       c    178     NA
## 4       d    172     70
## 5       e     NA     76
xy3<-merge(x = x,y = y,by = "student",all.x = T)
xy3
##   student height weight
## 1       a    160     53
## 2       b    156     42
## 3       c    178     NA
## 4       d    172     70


回到人口資料與死亡資料,利用 merge 整併。

data3<-merge(pop3,data2,by=c("year","county","sex","age","cause"),all=T)
data3[is.na(data3$num),7]<-0
rm(data)
rm(data2)
rm(ppp)
rm(pop2)


打印出來看看。

print(data3[c(1:10),])
##    year          county sex age cause   pop num
## 1  2012 Changhua County   1   1     1 29188   0
## 2  2012 Changhua County   1   1     2 29188   0
## 3  2012 Changhua County   1   1     3 29188   0
## 4  2012 Changhua County   1   1     4 29188   0
## 5  2012 Changhua County   1   1     5 29188   0
## 6  2012 Changhua County   1   1     6 29188   0
## 7  2012 Changhua County   1   1     7 29188   0
## 8  2012 Changhua County   1   1     8 29188   0
## 9  2012 Changhua County   1   1     9 29188   0
## 10 2012 Changhua County   1   1    10 29188   0