8.3 循环
在R中有三种循环:repeat
、while
和for
。虽然向量化意味着你可能并不像其他语言一样大量需要它们,但在需要重复执行代码时,它们还是很有用的。
8.3.1 重复循环
R中最容易掌握的循环是repeat
。它所做的事情就是反复地执行代码,直到告诉它停为止。在其他语言中,一般使用do while
或其他类似的方法完成。以下的例子1将反复执行,直到你按下Escape键、退出R或世界末日降临为止:
1 如果这些例子对你来说没有意义,请观看电影http://www.imdb.com/title/tt0107048。
repeat
{
message("Happy Groundhog Day!")
}
一般来说,我们还是希望在世界末日降临之前终止代码,因此需要一个break
语句以跳出无限循环。在下例中,sample
函数将在每个循环迭代中返回一个操作:
repeat
{
message("Happy Groundhog Day!")
action <- sample(
c(
"Learn French",
"Make an ice statue",
"Rob a bank",
"Win heart of Andie McDowell"
),
1
)
message("action = ", action)
if(action == "Win heart of Andie McDowell") break
}
## Happy Groundhog Day!
## action = Rob a bank
## Happy Groundhog Day!
## action = Rob a bank
## Happy Groundhog Day!
## action = Rob a bank
## Happy Groundhog Day!
## action = Win heart of Andie McDowell
有时候,我们想做的不是退出整个循环,而是跳过当前的迭代,开始next
下一次迭代而已:
repeat
{
message("Happy Groundhog Day!")
action <- sample(
c(
"Learn French",
"Make an ice statue",
"Rob a bank",
"Win heart of Andie McDowell"
),
1
)
if(action == "Rob a bank")
{
message("Quietly skipping to the next iteration")
next
}
message("action = ", action)
if(action == "Win heart of Andie McDowell") break
}
## Happy Groundhog Day!
## action = Learn French
## Happy Groundhog Day!
## Quietly skipping to the next iteration
## Happy Groundhog Day!
## Quietly skipping to the next iteration
## Happy Groundhog Day!
## action = Make an ice statue
## Happy Groundhog Day!
## action = Make an ice statue
## Happy Groundhog Day!
## Quietly skipping to the next iteration
## Happy Groundhog Day!
## action = Win heart of Andie McDowell
8.3.2 while
循环
while
循环就像是延迟了的repeat
循环。它不是先执行代码再检查循环是否应该结束,而是先进行检查再(可能)执行代码。因为检查发生在开始时,所以循环体有可能不会被执行(与repeat
循环不同)。在下例中,与以上repeat
的例子类似,除了当“Win heart of Andie McDowell”被抽中了,剩下的Groundhog Day循环语句则可完全避免:
action <- sample(
c(
"Learn French",
"Make an ice statue",
"Rob a bank",
"Win heart of Andie McDowell"
),
1
)
while(action != "Win heart of Andie McDowell")
{
message("Happy Groundhog Day!")
action <- sample(
c(
"Learn French",
"Make an ice statue",
"Rob a bank",
"Win heart of Andie McDowell"
),
1
)
message("action = ", action)
}
## Happy Groundhog Day!
## action = Make an ice statue
## Happy Groundhog Day!
## action = Learn French
## Happy Groundhog Day!
## action = Make an ice statue
## Happy Groundhog Day!
## action = Learn French
## Happy Groundhog Day!
## action = Make an ice statue
## Happy Groundhog Day!
## action = Win heart of Andie McDowell
使用一些小技巧能把repeat
循环转换为while
循环,或把while
循环转换为loop
循环,但通常使用其中一种语法会更简洁。如果你知道循环体必须至少执行一次,请使用repeat
,否则使用while
。
8.3.3 for
循环
第三种循环适用于已知代码所需执行的循环次数的情形。for
循环将接受一个迭代器变量和一个向量参数。在每个循环中,迭代器变量会从向量中取得一个值。最简单的情况下,该向量只包含整数:
for(i in 1:5) message("i = ", i)
## i = 1
## i = 2
## i = 3
## i = 4
## i = 5
如果你想执行多个表达式,与其他循环一样,须使用大括号把它们括起来:
for(i in 1:5)
{
j <- i ^ 2
message("j = ", j)
}
## j = 1
## j = 4
## j = 9
## j = 16
## j = 25
R的for
循环非常灵活,因为它们的输入并不限于整数或数字,还可以传入字符向量、逻辑向量或列表:
for(month in month.name)
{
message("The month of ", month)
}
## The month of January
## The month of February
## The month of March
## The month of April
## The month of May
## The month of June
## The month of July
## The month of August
## The month of September
## The month of October
## The month of November
## The month of December
for(yn in c(TRUE, FALSE, NA))
{
message("This statement is ", yn)
}
## This statement is TRUE
## This statement is FALSE
## This statement is NA
l <- list(
pi,
LETTERS[1:5],
charToRaw("not as complicated as it looks"),
list(
TRUE
)
)
for(i in l)
{
print(i)
}
## [1] 3.142
## [1] "A" "B" "C" "D" "E"
## [1] 6e 6f 74 20 61 73 20 63 6f 6d 70 6c 69 63 61 74 65 64 20 61 73 20 69
## [24] 74 20 6c 6f 6f 6b 73
## [[1]]
## [1] TRUE
因为for
循环操作于向量中的每个元素,所以它提供了一种“伪向量化”。事实上,R的向量化操作通常会在内部的C代码中使用某种形式的for
循环。但要注意:R的for
循环几乎总是比其对应的向量化运行得要慢,而且往往是一到两个数量级的差别。这意味着你应尽可能地使用向量化2。
2 有公论的是,如果你把R代码编写得和Fortran一样,就没资格抱怨R运行得太慢了。