R语言基础系列前情提要:
1数据类型(向量、数组、矩阵、 列表和数据框)
2读写数据所需的主要函数、与外部环境交互
3数据筛选——提取对象的子集
4:向量、矩阵的数学运算
R语言中控制结构可以用来控制程序的执行流程
常见控制结构的命令:
if
and else
: 测试逻辑条件
for
: 用于执行固定次数的循环
while
: 用于在某个条件成立时执行循环
repeat
: 执行无限循环
break
: 终止并跳出循环
next
: 跳过循环中的当前迭代
return
: 从函数中退出
如果条件成立,程序就做某件事
否则(另一种条件下)。程序做另一件事
if() {
## do something
}
else {
## do something else
}
Else不是必须的,如果只需要在某条件成立时执行某个任务,那么只要使用if语句就可以了
if() {
## do something
}
## Continue with rest of code
如果条件不止一个/不止两个的时候,可以添加一个/多个 elseif
语句,但最后必须以 else
结尾:
if() {
## do something
} else if() {
## do something different
} else {
## do something different
}
取随机数字举例,y的取值随x的取值而定:
## Generate a uniform random number
x <- runif(1, 0, 10)
x
if(x > 3) {
y <- 10
} else {
y <- 0
}
上面的代码也可以写成下面的形式,先给变量y赋值,这种写法的好处是更加明确的看出整个if结构是在给y赋值:
y <- if(x > 3) {
10
} else {
0
}
for
循环是R中最常见的循环运算符,基本思路是先要设定一个循环下标,通常命名为 i
,循环下标通常会代表一个整数数列中的每一个数字,或列表中的每一个对象等等。
最简单的例子如下,运行后将依次输出1-10这十个整数:
for(i in 1:10) {
print(i)
}
依次打印x中的每一个元素,运行后就会依次输出 "a"
, "b"
, "c"
, "d"
四个字符对象:
第一种方法是将循环向量和向量x的长度相对应:
x <- c("a", "b", "c", "d")
for (i in 1:4) {
print(x[i])
}
第二个方法,使用 seq_along()
函数,即,输入一个向量,之后它就会创造一个与该向量等长的整数数列。因此上面的例子可以改写成,在我们不知道x的向量长度时,可以使用这种写法:
x <- c("a", "b", "c", "d")
for (i in seq_along(x)) {
print(x[i])
}
第三个方法,下标变量 letter
,这个变量的本意就是一个下标,会从向量本身取值,它可以从任意向量中提取元素,因此可以写成:
x <- c("a", "b", "c", "d")
for (letters in x) {
print(letters)
}
ps. 如果你的for循环表达式只有一行,那么可以省略掉大括号 {}
,直接写道 for
的后面:
for (letters in x) print(letters)
把一个for循环放到另一个for循环的里面。
比如,有一个二维矩阵,你想先做一个行循环,再做一个列循环,这时就需要做一个嵌套for结构才能打印出所有矩阵中的元素。
我们设置 i
为外层循环下标, j
为内层循环下标:
> x <- matrix(1:6, 2, 3)
> x
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> for (i in seq_len(nrow(x))) {
+ for (j in seq_len(ncol(x))) {
+ print(x[i,j])
+ }
+ }
[1] 1
[1] 3
[1] 5
[1] 2
[1] 4
[1] 6
While循环有一个逻辑表达式,循环是按照这个逻辑表达式的值来反复运行的。
举个栗子,
设定一个计数标量 count
,初始值为0,当技术变量的值小于10(逻辑表达式)时,运行输出变量 count
就在之前的基础上 +1
,一旦 count
的值达到10,循环停止
count <- 0
while(count < 10) {
print(count)
count <- count + 1
}
注意:你需要确保逻辑循环表达式的值是可以达到终止状态的,否则就会无穷无尽的循环下去。
再举个栗子,设计一个小型随机游走的程序:
首先赋值z=5,然后运行while循环,当z处于3~10中间时,进入循环,循环中抛硬币,硬币是随机数1和0.5,在嵌入if循环,z的值会根据硬币取值变化而变化,结束时间不定。
z <- 5
while (z >= 3 && z <= 10) {
coin <- rbinom(1, 1, 0.5)
if(coin == 1) { ## random walk
z <- z + 1
} else {
z <- z - 1
}
}
这是一个无限循环结构,退出的方法是 break
(在某个点强制退出)。
比如,当你想计算两个值何时达到无限接近,需要通过算法不断循环,直到逼近你设置的容差(允许范围)
x0 <- 1
tol <- 1e-8
repeat {
x1 <- computeEstimate()
if(abs(x1 - x0) < tol) { ## Close enough?
break
} else {
x0 <- x1
}
}
(这里的 computeEstimate()
是需要事先设定的,如果这有这段这个代码的话跑不通)
注意,repeat循环风险很大,因为没硬性规定何时退出,有可能运行时间非常长,所以不建议直接使用
break
用来完全退出循环
for(i in 1:100) {
print(i)
if(i > 20) {
## Stop loop after 20 iterations
break
}
}
next
和 return
函数是一种控制结构。
next
可用在任何一种循环中,跳过某一段循环。例如,在1-100的迭代循环中,想要跳过前20个,可以用这种方式:
for(i in 1:100) {
if(i <= 20) {
## Skip the first 20 iterations
next
}
## Do something here
}
return
主要用于退出函数,它会结束整个函数并且返回一个数值。
最后,Peng提到,这些控制结构最好用于编写程序的过程中,而在命令行和交互作用来说有其他的循环函数,如apply()等一系列函数,这些在这里暂且不提,以后会讲到。
参考资料:
https://bookdown.org/rdpeng/rprogdatascience/R Programming for Data Science
《R语言实战》 Robert I. Kabacoff
快快和我一起上车,请关注:生信小白学习记
热文:1高分文章 2不可或缺的人 3图表规范
一文读懂:1微生物组 2寄生虫益处 3进化树
必备技能:1提问 2搜索 3Endnote
文献阅读 1热心肠 2SemanticScholar 3geenmedical
扩增子分析:1图表解读 2分析流程 3统计绘图 4功能预测
科研经验:1云笔记 2云协作 3公众号
系列教程:1Biostar 2微生物组 3宏基因组
生物科普 1肠道细菌 2人体上的生命 3生命大跃进 4细胞的暗战 5人体奥秘
为鼓励读者交流、快速解决科研困难,我们建立了“宏基因组”专业讨论群,目前己有国内外1300+ 一线科研人员加入。参与讨论,获得专业解答,欢迎分享此文至朋友圈,并扫码加主编好友带你入群,务必备注“姓名-单位-研究方向-职称/年级”。技术问题寻求帮助,首先阅读《如何优雅的提问》学习解决问题思路,仍末解决群内讨论,问题不私聊,帮助同行。
学习16S扩增子、宏基因组科研思路和分析实战,关注“宏基因组”