R語言之控制流的使用方法

R語言之控制流的使用方法

來自專欄 R語言中文社區10 人贊了文章

作者:劉順祥

公眾號:數據分析1480 (微信ID:lsxxx2011)

配套教程:手把手教你做文本挖掘 edu.hellobi.com/course/

般在數據處理或建模過程中會使用到R語言中的控制流,控制流主要有以下三類,即

1)if或switch分支語句

2)for循環

3)while循環

下面就說說這幾種控制流,並講解我工作中的用法。

一、if或switch分支語句

首先看一下if分支語句,一般有雙分支和多分支。關於這兩種分支我們看下圖:

對於二分支,我個人更喜歡使用ifelse()函數,該函數是R語言內置的函數,運行速度是非常快的。下面舉個例子來說明一下:

```{r}

x <- rnorm(100000)

y <- numeric()

system.time(

for(i in 1:length(x)){

if(x[i]<0.5) y[i] = 0

else y[i] = 1

}

)

system.time(y <- ifelse(x<0.5, 0, 1))

```

同樣的目的,但兩者的差距是非常大的。

如果在實際業務中,二分支不能夠解決問題的話,這時就不得不考慮多分支的if語句了,下面舉個應用的場景:

```{r}

#隨機生成性別向量

gender <- sample(c(F,M,Unknow), size = 100000, replace = TRUE)

#現在需要解決的一個問題是,重編碼,即F改為Female,M改為Male,其他不變,一般會考慮使用if的多分支語句解決該問題

gender2 <- character()

system.time(

for(i in 1:length(gender)){

if(gender[i]==F) gender2[i] = Female

else if(gender[i]==M) gender2[i] = Male

else gender2[i] = Unknow

}

)

```

很明顯,對於10W行的數據,這樣的多分支仍然顯得非常慢,這個時候我建議使用switch分支語句,該語句的語法如下:

其實就是對號入座,需要哪條分支,就返回哪條分支的結果,但case只能是一個值,所以還需要配合sapply函數一起使用

```{r}

#將字元變數設為有序因子

gender3 <- factor(gender, levels = c(F,M,Unknow))

#自定義switch函數返回值

s <- function(case) switch(case,Female,Male,Unknow)

system.time(gender4 <- sapply(as.numeric(gender3),s))

```

這樣的效率還是非常高的,一般多水平的離散變數重編碼一一對應時問題建議使用switch分支語句當然你還可以使用within語句實現該功能,如:

```{r}

system.time(

within(data.frame(gender),{

gender5 <-

gender5[gender==F] <- Female

gender5[gender==M] <- Male

gender5[gender==Unknow] <- Unknow

})

)

```

雖然使用within()函數實現重編碼有一點點複雜,但計算效率還是非常高的!

二、for循環

其實在講if分支語句時,我們就用到了for循環,for循環實質上是對某個對象進行遍歷一般for循環會配合if語句進行遍歷的條件判斷,下面通過一個實例來看看for循環的應用:

方法一:

```{r}

score <- round(runif(100000, min = 40, max = 92))

#計數器

i <- 1

score2 <-

system.time(

for (score in score){

if (score<60) score2[i] <- 不及格

else if (score>=60 & score<80) score2[i] <- 合格

else score2[i] <- 優秀

i <- i + 1

}

)

```

該方法是不知道該循環多少次時,可以使用這種for語句直接遍歷向量中的每一個值。

方法二:

```{r}

score <- round(runif(100000, min = 40, max = 92))

score3 <-

system.time(

for (i in 1:length(score)){

if (score[i]<60) score3[i] <- 不及格

else if (score[i]>=60 & score[i]<80) score3[i] <- 合格

else score3[i] <- 優秀

}

)

```

在知道循環多少次的前提下可使用這樣的for語句上面這個例子不是一對一的重編碼問題,建議使用within()內置函數解決編碼,可以大大提高計算速度。

```{r}

score <- round(runif(100000, min = 40, max = 92))

system.time(

score <- within(data.frame(score),{

score4 <-

score4[score<60] <- 不及格

score4[score>=60 & score<80] <- 合格

score4[score>=80] <- 優秀

})

)

```

如果不是這樣的重編碼問題,可能就需要硬著頭皮使用for循環和if判斷條件了,這種顯式for循環會拉低R的計算效率。當然,還有一種可彌補的方法就是使用sapply()函數

三、while循環

while循環語法:

i <- 1

while(condition){

statements

i = i + 1

}

這裡必須強調的是,while循環語句中必須給一個計數器i,否則無法進行一輪又一輪的循環迭代操作。這裡舉一個簡單的計算1~1000的和:

```{r}

s <- 0

i <- 1

while(i<=1000){

s <- s + i

i <- i + 1

}

s

```

其實,for循環基本可以替代while循環語句,在實際的工作中,我比較喜歡使用for循環,因為for循環可以實現「已知循環次數」和「未知循環次數」的功能,而且for循環也更加直觀。

參考資料:

《統計建模與R軟體》

《R語言與網站分析》


推薦閱讀:

數學倒底有什麼用?
死做10000道數學題,不如活讀這20本趣味數學圖書
管理類聯考高分數學(管綜177分)超詳細複習時間規劃及筆記分享(附學習小秘訣)
中國數學界掃地僧:當過服務生,蟄伏三十年拿遍榮譽

TAG:編程語言 | 自然科學 | 數學 |