# 循环结构{#R:loop-structure}
所有现代编程语言都提供允许重复指令或指令快的特殊构造。在R中当需要重复做某动作时,可运用循环结构。比如1+2+3,我们可以直接写表达式,但是1+2+3+...+100,我们不可能直接写表达式,这时就可以借用循环重复计算。
```{r}
1+2+3
```
![loop-structure](picture/loop/loop-structure.png)
## R循环介绍{#R:loop-description}
通过命令`?Control`可以查看R中的循环结构。循环结构中关键词`for`,`while`,`repeat`,以及`break`,`next`。
**我们终极目是:清晰了解循环结构后,用向量化或purrr包提供的功能摆脱循环。**
### 简单示例{#R:loop-example}
利用循环实现1到100连续相加求和
```{r}
total 循环中尽可能利用R中的向量化,比如指定output的长度,当数据量大的时候效率提升将比较明显,养成向量化的意识对提高代码效率有显著效果.
- while
当我们不知道要循环迭代的次数时,可以考虑使用while循环结构。
示例如下:
```{r eval=FALSE}
readinteger 100){
print(paste0('连续相加求和等于:',total))
break
}
}
```
### 循环控制{#loop:control}
R中如何中断或退出循环呢?除了自然结束的for循环,while,repeat是如何结束的呢,在R中,我们可以通过`break`以及`next`控制循环,上一示例中我们已经看到`break`是如何跳出循环的。
- next 用法
```{r}
for(i in letters[1:6] ){
if(i == "d"){
next
}
print(i)
}
```
- break 用法
当条件满足时,跳出循环。
```{r}
m=10
n=10
ctr=0
mymat = matrix(0,m,n)
for(i in 1:m) {
for(j in 1:n) {
if(i==j) {
break;
} else {
# you assign the values only when i<>j
mymat[i,j] = i*j
ctr=ctr+1
}
}
print(i*j)
}
# 共赋值多少次
print(ctr)
```
### 嵌套循环
嵌套循环即在循环体中再循环。
```{r}
# not run
v apply系列函数简洁高效的原因是因为 R 语言里面的向量化,具体可以参考《R语言编程艺术》。
### lapply 循环迭代 {#lapply}
lapply 是 list 和 apply 的结合,lapply是对向量或列表数据应有一个功能函数,返回的数据结构是和前面的数据长度相等的列表。函数的参数如下:
```{r eval=FALSE}
lapply(X, FUN, ...)
```
其参数说明如下:
X: 一个向量或列表,或者是"expression" ,同样是列表。关于"expression" 可以查看帮助`?expression`。
FUN:需要运行的函数,可以是任意函数,无论是base R ,R packages,或者是自定义的函数。
...: 函数中其它参数的设置,如有需要的话。
我们首先看一个简单的示例:
```{r}
x lapply 是 apply 系列函数中我唯一一个可能使用的
### sapply {#sapply}
sapply 是lapply的简化版。函数的参数如下:
```{r eval=FALSE}
sapply(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)
```
和 lapply 函数的参数差异,simplify 默认为TRUE,是否返回向量,矩阵,数组,如果情况允许。我们用lapply 的例子查看 sapply 的功能。
```{r}
sapply(x ,mean)
sapply(x ,mean,na.rm=TRUE)
```
### vapply 迭代安全函数{#vapply}
vapply 函数通过FUN.VALUE 参数确保返回值长度以及类型一致,详见`?vapply`。
- 长度
```{r}
x Error in vapply(x, function(x) x[x == 3], FUN.VALUE = 1) :
#> 值的长度必需为1,
#> 但FUN(X[[2]])结果的长度却是2
# 同上
# vapply(x,function(x) x[x==3],FUN.VALUE = as.numeric(1))
vapply(y,function(x) x[x==3],FUN.VALUE = as.numeric(1))
```
相同的列表,相同的函数,使用 sapply 会返回信息不会报错,但是使用 vapply 会报错,因为b中有2个3,而a,d中只有1个3。
- 类型
```{r eval=FALSE}
x Error in vapply(x, mean, FUN.VALUE = 1L) : 值的种类必需是'integer',
#> 但FUN(X[[1]])结果的种类却是'double'
```
> vapply 函数的 FUN.VALUE 参数必须设置,可以通过 as.integer/character等函数进行设置
### apply 多维数据{#apply}
apply 专门用来处理矩阵和数组数据。参数如下:
```{r eval=FALSE}
apply(X, MARGIN, FUN, ..., simplify = TRUE)
```
其中 MARGIN 参数,1代表行,2代表列,`c(1,2)`代表行列。
```{r}
x 对于大部分商业数据分析师而言,较少遇到多维数据集