R擁有一般現(xiàn)代編程語言中都有的標準控制結(jié)構(gòu)方妖。在學習控制流之前生宛,應該理解以下概念:
語句(statement)是一條單獨的R語句或一組復合語句(包含在花括號{ } 中的一組R語句匠襟,使用分號分隔)祟敛;
條件(cond)是一條最終被解析為真(TRUE)或假(FALSE)的表達式;
表達式(expr)是一條數(shù)值或字符串的求值語句佣蓉;
序列(seq)是一個數(shù)值或字符串序列披摄。
1. 重復與循環(huán)
1.1 for結(jié)構(gòu)
for循環(huán)重復地執(zhí)行一個語句,直到某個變量的值不再包含在序列seq中為止勇凭。
for (var in seq) statement
若要將“Hello”打印10次:
> for (i in 1:10)
+ print("Hello!")
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
1.2 while結(jié)構(gòu)
while循環(huán)重復地執(zhí)行一個語句疚膊,直到條件不為真為止。
while (cond) statement
同樣虾标,我們再來重復輸出10次“Hello寓盗!”
> i <- 10
> while (i > 0) {
+ print("Hello!");
+ i <- i - 1}
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
[1] "Hello!"
需要注意的是,在處理大數(shù)據(jù)集中的行和列時璧函,R中的循環(huán)可能比較低效費時傀蚌。只要可能,最好聯(lián)用R中的內(nèi)建數(shù)值/字符處理函數(shù)和apply
族函數(shù)蘸吓。這與其他的大量使用循環(huán)的語言是有區(qū)別的善炫。
2. 條件執(zhí)行
在條件執(zhí)行結(jié)構(gòu)中, 一條或一組語句僅在滿足一個指定條件時執(zhí)行库继。 條件執(zhí)行結(jié)構(gòu)包括 if-else
箩艺、ifelse
和switch
窜醉。
2.1 if-else
結(jié)構(gòu)
控制結(jié)構(gòu)if-else在某個給定條件為真時執(zhí)行語句。也可以同時在條件為假時執(zhí)行另外的語句:
if (cond) statement
if (cond) statement1 else statement2
> a=5
> b=6
> if (a < b) {a <- -1
+ } else if (a == b) {a <- 0
+ } else {a <- 1}
> print(a)
[1] -1
2.2 ifelse
結(jié)構(gòu)
ifelse
結(jié)構(gòu)是if-else
結(jié)構(gòu)比較緊湊的向量化版本艺谆,其語法為:
ifelse(cond,statement1,statement2)
若cond
為TRUE
酱虎,則執(zhí)行第一個語句;若cond
為FALSE
擂涛,則執(zhí)行第二個語句。
> x <- factor(sample(letters[1:5], 10, replace = TRUE))
> x
[1] a a c d a b d b d d
> ifelse(x %in% c("a", "b", "c"), x, factor(NA))
[1] 1 1 3 NA 1 2 NA 2 NA NA
2.3 switch
結(jié)構(gòu)
switch(expr,...)
switch
根據(jù)一個表達式的值選擇語句執(zhí)行聊记。其中的...表示與expr
的各種可能輸出值綁定的語句撒妈。
> feelings <- c("sad","afraid")
> for (i in feelings)
+ print(switch(i,
+ happy = "I am happy today",
+ afraid = "There is nothing to fear",
+ sad = "cheer up",
+ angry = "calm down now"))
[1] "cheer up"
[1] "There is nothing to fear"
#當表達式(exp)匹配后續(xù)的參數(shù)名(即變量名)時,返回參數(shù)的值
> t = "r"
> switch(t,r='re',g='gr',b='bl',"error")
[1] "re"
#如果不匹配任何參數(shù)名排监,switch函數(shù)不返回任何值狰右,可以添加一個匿名的參數(shù),
#當表達式(exp)匹配不上任意一個命名參數(shù)時舆床,switch函數(shù)將返回匿名參數(shù)的值:
> t = "xs"
> switch(t,r='re',g='gr',b='bl',"error")
[1] "error"
3. 用戶自編函數(shù)
R的最大優(yōu)點之一就是用戶可以自行添加函數(shù)棋蚌。
myfunc <- function(arg1,arg2,....)
{
statements
return(object)
}
#example1
> avg <- function(a,b){
+ c <- mean(c(a,b));
+ return(c)
+ }
> avg(3,4)
[1] 3.5
#example2
#練習一個每次學循環(huán)都要做的矩陣的乘法
matrixf <- function(a,b){
row1 <- dim(a)[1]
col1 <- dim(a)[2]
row2 <- dim(b)[1]
col2 <- dim(b)[2]
if (col1 == row2) {
result <- matrix(0,nrow = row1,ncol = col2)
for (i in 1:row1)
for (j in 1:col2)
result[i,j] <- sum(a[i,]*b[,j])
return(result)
}
else {
print("error")
return(0)
}
}
> a <- matrix(10,2)
> a
[,1]
[1,] 10
[2,] 10
> a <- (c(1:4,2))
> a
[1] 1 2 3 4 2
> a <- matrix(1:4,2)
> a
[,1] [,2]
[1,] 1 3
[2,] 2 4
> b <- matrix(1:4,2)
> b
[,1] [,2]
[1,] 1 3
[2,] 2 4
> matrixf(a,b)
[,1] [,2]
[1,] 7 15
[2,] 10 22
4. 整合與重構(gòu)
R中提供了許多用來整合(aggregate)和重塑(reshape)數(shù)據(jù)的強大方法。
4.1 轉(zhuǎn)置
轉(zhuǎn)置即反轉(zhuǎn)列和行挨队,適用于矩陣和數(shù)據(jù)框谷暮,使用函數(shù)t()
即可完成。
> head_cars <- head(mtcars,6)
> head_cars
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21 6 160 110 3.9 2.6 16 0 1 4 4
Mazda RX4 Wag 21 6 160 110 3.9 2.9 17 0 1 4 4
Datsun 710 23 4 108 93 3.9 2.3 19 1 1 4 1
Hornet 4 Drive 21 6 258 110 3.1 3.2 19 1 0 3 1
Hornet Sportabout 19 8 360 175 3.1 3.4 17 0 0 3 2
Valiant 18 6 225 105 2.8 3.5 20 1 0 3 1
> t(head_cars)
Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout Valiant
mpg 21.0 21.0 22.8 21.4 18.7 18.1
cyl 6.0 6.0 4.0 6.0 8.0 6.0
disp 160.0 160.0 108.0 258.0 360.0 225.0
hp 110.0 110.0 93.0 110.0 175.0 105.0
drat 3.9 3.9 3.9 3.1 3.1 2.8
wt 2.6 2.9 2.3 3.2 3.4 3.5
qsec 16.5 17.0 18.6 19.4 17.0 20.2
vs 0.0 0.0 1.0 1.0 0.0 1.0
am 1.0 1.0 1.0 0.0 0.0 0.0
gear 4.0 4.0 4.0 3.0 3.0 3.0
carb 4.0 4.0 1.0 1.0 2.0 1.0
4.2 整合數(shù)據(jù)
在R中使用一個或多個by變量和一個預先定義好的函數(shù)來折疊(collapse)數(shù)據(jù)是比較容易的:
aggregate(x,by,FUN)
x是待折疊的數(shù)據(jù)對象
by是一個變量名組成的列表盛垦,這些變量將被去掉以形成新的觀測
FUN則是用來計算描述性統(tǒng)計量的標量函數(shù)湿弦,它將被用來計算新觀測中的值。
> detach(mtcars)
> options(digits = 3)
> attach(mtcars)
> aggdate <- aggregate(mtcars,by = list(cyl,gear),FUN=mean,na.rm = TRUE)
> print(aggdate)
Group.1 Group.2 mpg cyl disp hp drat wt qsec vs am gear carb
1 4 3 21.5 4 120 97 3.70 2.46 20.0 1.0 0.00 3 1.00
2 6 3 19.8 6 242 108 2.92 3.34 19.8 1.0 0.00 3 1.00
3 8 3 15.1 8 358 194 3.12 4.10 17.1 0.0 0.00 3 3.08
4 4 4 26.9 4 103 76 4.11 2.38 19.6 1.0 0.75 4 1.50
5 6 4 19.8 6 164 116 3.91 3.09 17.7 0.5 0.50 4 4.00
6 4 5 28.2 4 108 102 4.10 1.83 16.8 0.5 1.00 5 2.00
7 6 5 19.7 6 145 175 3.62 2.77 15.5 0.0 1.00 5 6.00
8 8 5 15.4 8 326 300 3.88 3.37 14.6 0.0 1.00 5 6.00
> detach(mtcars)
簡單解釋一下數(shù)據(jù)腾夯,Group1
即cyl
颊埃,Group2
即gear
,則第一行的數(shù)據(jù)表示cyl為4蝶俱、gear為3的所有車的其它變量disp
班利,hp
等的平均值。
這是非痴ゴ簦可怕的功能罗标,可以自由的折疊,提取數(shù)據(jù)子集积蜻。
需要注意的一點是馒稍,在使用aggregate()
函數(shù)的時候,by
中的變量必須在一個列表中(即使只有一個變量)浅侨。
4.3 reshape2
reshape2包是一套重構(gòu)和整合數(shù)據(jù)集的絕妙的萬能工具纽谒。我們將在下節(jié)專題介紹。