R语言是以向量化编程而闻名的。因此R的for循环相比于向量化操作而言有时候会较慢。
R – for loop
1  | for (variable in vector) {  | 
有两种方法可以提前终止for循环
next退出当前迭代break退出整个for循环
1  | for (i in 1:10) {  | 
1  | [1] 3  | 
下面用以下的例子实测R语言中的循环的效率。
- 使用 for 循环取一千万个数值的绝对值,并使用
system.time函数测量函数运行的时间。 
1  | #生成一个包含正数和负数的长向量,总共有一千万个数值  | 
- 再使用R中向量化的方式进行上述操作
 
1  | abs_set <- function(x){  | 
在使用了R中向量化编程的方式(逻辑判断、取子集、元素方式执行)后,速度提升了大约30倍。
- 最后,我们看看R中自带的取绝对值函数
abs有多快R中的自带函数几乎是1
2
3> system.time(abs(long))
用户 系统 流逝
0.02 0.02 0.03for循环速度运行的300倍!这是由于R中很多basic的函数都是经过多次优化与调试的,所以在可能的情况下,应该尽量避免对其自带函数的修改。 
for循环常见的使用错误
通过循环赋值时,要预先生成变量
如果我们需要通过for循环赋值,我们需要预先生成好容器变量,并设置变量相应属性,这将会提升for循环的效率
假设我们需要在1000个不同均值的正态分布中随机抽取1000个数,并存储到列表中:
1  | means <- c(1:1000)  | 
可以发现使用vector()预先设置好容器的长度将会提升for循环赋值的速度约2.3倍
使用seq_along()迭代
上面我们使用1:length(mean)对mean向量进行迭代,但这种方法在向量为空时将会报错。
1  | means <- c()  | 
因此,尽可能使用seq_along()对向量进行迭代。seq_along()返回与输入向量等长的序列
1  | > seq_along(11:20)  | 
所以,如果向量为空也不用担心报错
1  | seq_along(means)  | 
S3向量的循环
有时候,对S3向量进行迭代时,我们也可能碰到以下问题
1  | xs <- as.Date(c("2020-01-01", "2010-01-01"))  | 
这是由于循环解除了变量的属性,这个时候使用双中括号[[可以解决
1  | for (i in seq_along(xs)) {  | 
总而言之,for循环会比较符合我们的直观思维,但在R中向量化编程的方式会提高我们处理任务的效率。当然,有时候向量化编程也会起到反作用,切记具体情况具体分析,而不是死磕一种方法。
Ref:
Advanced R: https://adv-r.hadley.nz/control-flow.html
完。