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

一般在数据处理或建模过程中会使用到R语言中的控制流,控制流主要有以下三类,即

1)if或switch分支语句

2)for循环

3)while循环

下面就说说这几种控制流,并讲解我工作中的用法。


一、if或switch分支语句

首先看一下if分支语句,一般有双分支和多分支。关于这两种分支我们看下图:

0?wx_fmt=png
对于二分支,我个人更喜欢使用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))

```

0?wx_fmt=png
同样的目的,但两者的差距是非常大的。


如果在实际业务中,二分支不能够解决问题的话,这时就不得不考虑多分支的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'

}

)

```

0?wx_fmt=png
很明显,对于10W行的数据,这样的多分支仍然显得非常慢,这个时候我建议使用switch分支语句,该语句的语法如下:

0?wx_fmt=png
其实就是对号入座,需要哪条分支,就返回哪条分支的结果,但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))

```

0?wx_fmt=png
这样的效率还是非常高的,一般多水平的离散变量重编码一一对应时问题建议使用switch分支语句当然你还可以使用within语句实现该功能,如:

```{r}

system.time(

  within(data.frame(gender),{

  gender5 <- ''

  gender5[gender=='F'] <- 'Female'

  gender5[gender=='M'] <- 'Male'

  gender5[gender=='Unknow'] <- 'Unknow'

})

)

```

0?wx_fmt=png
虽然使用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

  }

)

```

0?wx_fmt=png
该方法是不知道该循环多少次时,可以使用这种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] <- '优秀'

  }

)

```

0?wx_fmt=png
在知道循环多少次的前提下可使用这样的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] <- '优秀'

                  })

)

```

0?wx_fmt=png
如果不是这样的重编码问题,可能就需要硬着头皮使用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

```

0?wx_fmt=png
其实,for循环基本可以替代while循环语句,在实际的工作中,我比较喜欢使用for循环,因为for循环可以实现“已知循环次数”和“未知循环次数”的功能,而且for循环也更加直观。


参考资料:

《统计建模与R软件》

《R语言与网站分析》



每天进步一点点2015

学习与分享,取长补短,关注小号!

0?wx_fmt=jpeg

  长按识别二维码à马上关注

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值