for 循环通过迭代一个给定向量或列表,重复执行某个表达式。for 循环的语法是
这样的:
for (var in vector) {
expr
}
var 遍历 vector 中的各个元素值,expr 被反复迭代执行。如果 vector 中有 n 个
元素,那么上述循环就等价于:
var <- vector[[1]]
expr
var <- vector[[2]]
expr
...
var <- vector[[n]]
expr
例如,我们使用迭代变量 i 来构造一个在 1:3 上迭代的循环,并且每次迭代,都把变
量 i 的取值信息输出到屏幕上:
for (i in 1:3){
cat("The value of i is",i,"\n")
}
## The value of i is 1
## The value of i is 2
## The value of i is 3
迭代可作用于所有类型的向量,而不只是数值向量。例如,我们可以用一个字符向量
替代 1:3 这一整数向量:
for (word in c("hello", "new", "world")) {
cat("The current word is", word, "\n")
}
## The current word is hello
## The current word is new
## The current word is world
也可以用一个列表来替代它:
loop_list <- list(
a = c(1, 2, 3),
b = c("a", "b", "c", "d"))
for (item in loop_list) {
cat("item:\n length:", length(item),
"\n class:", class(item), "\n")
}
## item:
## length: 3
## class: numeric
## item:
## length: 4
## class: character
除此之外,还可以用数据框来替代它:
df <- data.frame(
x = c(1, 2, 3),
y = c("A", "B", "C"),
stringsAsFactors = FALSE)
for (col in df) {
str(col)
}
## num [1:3] 1 2 3
## chr [1:3] "A" "B" "C"
之前我们提到过,数据框是一个列表,每一元素(列)的长度必须相同。因此,上述
循环的运行方式和对一个普通列表执行 for 循环是一致的,都是按列,而不是按行进行迭代。
然而,很多时候,我们想按行迭代一个数据框。这时可以使用 for 循环,在一个整数
序列(1 到数据框的行数)上迭代。
i 每次取一个行数,我们就把这一行从数据框中挑出来,然后对这一特定的行进行相
应的操作。以下代码按行迭代数据框,并使用 str( ) 输出每一行的结构:
for (i in 1:nrow(df)) {
row <- df[i,]
cat("row", i, "\n")
str(row)
cat("\n")
}
## row 1
## 'data.frame': 1 obs. of 2 variables:
## $ x: num 1
## $ y: chr "A"
##
## row 2
## 'data.frame': 1 obs. of 2 variables:
## $ x: num 2
## $ y: chr "B"
##
## row 3
## 'data.frame': 1 obs. of 2 variables:
## $ x: num 3
## $ y: chr "C"
这里要给一个小小的警告。一般来说,按行迭代数据框并不是一个好主意,因为迭代
过程可能很慢很繁琐。更好的方法是使用第 5 章中介绍的 apply 函数族,或者第 12 章中
介绍的更强大、更高级的扩展包。
在前面的例子中,for 循环的每一次迭代都是相互独立的。有时,可以利用循环外的
变量来记录迭代状态或累积过程。最简单的例子是计算从 1~100 的和:
s <- 0
for (i in 1:100){
s <- s + i
}
s
## [1] 5050
上述例子展示了使用 for 循环进行累计求和。接下来的例子中,我们使用随机数生成
器从正态分布中进行抽样,简单地模拟一下随机游走过程(random walk):
set.seed(123)
x <- numeric(1000)
for (t in 1:(length(x) -1)) {
x[[t + 1]] <- x[[t]] + rnorm(1, 0, 0.1)
}
plot(x, type = "s", main = "Random walk", xlab = "t")
以上代码的输出结果,如图 4-1 所示。
图 4-1
上述两个例子中,尽管 for 循环过程的每一步都依赖于上一步的结果,但可以利用现
有函数,如 sum( ) 和 cumsum( ) 简化循环结构:
sum100 <- sum(1:100)
random_walk <- cumsum(rnorm(1000,0,0.1))
这些函数的基本思想和 for 循环类似,但它们是基于 C 语言的向量化实现,所以运
行效率远高于 R 中的 for 循环。因此,在可能的情况下,应该优先考虑使用这些内置函数。
1.管理 for 循环的控制流
有时,有必要对 for 循环进行干预。在每一次迭代中,我们可以选择中断 for 循环,
跳过当前迭代,或者什么都不做并终止循环。
可以使用 break 终止 for 循环:
for (i in 1:5) {
if(i == 3) break
cat("message", i, "\n")
}
## message 1
## message 2
这种方法可以用来寻找某个问题的解。以下代码试图在 1000 至 1100 之间找到满
足 (i ^ 2) %% 11 等于 (i ^ 3)%%17 的数,其中 ^ 是指数运算符,%% 是除法运算中的取
余运算符:
m <- integer()
for (i in 1000:1100) {
if ((i ^ 2) %% 11 == (i ^ 3) %% 17){
m <- c(m, i)
}
}
m
## [1] 1055 1061 1082 1086 1095
如果只要该范围内满足条件的一个数,你可以将记录追踪表达式(m <-c(m,i))替
换成一个简单的 break:
for (i in 1000:1100) {
if ((i ^ 2) %% 11 == (i ^ 3) %% 17) break
}
i
## [1] 1055
一旦找到一个解,for 循环就会终止,并将 i 的最后取值保存在当前环境中,这样就
能得到满足条件的解。
有时,也可能需要跳过 for 循环中的某一次迭代。我们可以使用 next 跳过本次迭代
的剩余部分,直接进入循环的下一次迭代:
for (i in 1:5) {
if (i == 3) next
cat("message ", i, "\n")
}
## message 1
## message 2
## message 4
## message 5
2.创建循环嵌套
for 循环中的表达式可以是任何内容,包括另一个 for 循环。例如,如果我们想要穷
举向量中元素的所有排列,可以写一个嵌套两层的 for 循环来解决这个问题:
x <- c("a", "b", "c")
combx <- character()
for (c1 in x){
for (c2 in x) {
combx <- c(combx, paste(c1, c2, sep = ",", collapse = ""))
}
}
combx
## [1] "a,a" "a,b" "a,c" "b,a" "b,b" "b,c" "c,a" "c,b" "c,c"
如果只要不同元素的排列,可以在 for 循环内部加一个判定条件:
combx2 <- character()
for (c1 in x) {
for (c2 in x) {
if (c1 == c2) next
combx2 <- c(combx2, paste(c1, c2, sep = ",", collapse = ""))
}
}
combx2
## [1] "a,b" "a,c" "b,a" "b,c" "c,a" "c,b"
除此之外,也可以去掉判定条件,把 for 循环内部的表达式替换为以下代码,以得到
完全相同的结果:
if (c1 != c2) {
combx2 <- c(combx2, paste(c1, c2, sep = ",", collapse = ""))
}
上述代码展示了嵌套循环是如何工作的,但它并不是解决这个问题的最佳方法。一些
内置函数就可以生成向量元素的排列或组合。给定一个原子向量和每个组合的元素个数,
函数 combn( ) 返回由相应组合构成的一个矩阵:
combn(c("a", "b", "c"), 2)
## [,1] [,2] [,3]
## [1,] "a" "a" "b"
## [2,] "b" "c" "c"
与之类似,函数 expand.grid( ) 返回由相应排列构成的一个数据框:
expand.grid(n = c(1, 2, 3), x = c("a", "b"))
## n x
## 1 1 a
## 2 2 a
## 3 3 a
## 4 1 b
## 5 2 b
## 6 3 b
尽管 for 循环很强大,但 R 中有很多针对特定任务编写的函数。最好优先考虑使用内
置函数,而不是直接把所有内容放到 for 循环中。在下一章中,我将会介绍能够代替许
多 for 循环的 lapply( ) 函数和其他相关函数,这些函数使代码更易于编写和理解。

使用 for 循环的更多相关文章

  1. 【.net 深呼吸】细说CodeDom(8):分支与循环

    有人会问,为啥 CodeDom 不会生成 switch 语句,为啥没生成 while 语句之类.要注意,CodeDom只关心代码逻辑,而不是语法,语法是给写代码的人用的.如果用.net的“反编译”工具 ...

  2. Recurrent Neural Network系列1--RNN(循环神经网络)概述

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 本文翻译自 RECURRENT NEURAL NETWORKS T ...

  3. Python学习--04条件控制与循环结构

    Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...

  4. 模仿Linux内核kfifo实现的循环缓存

    想实现个循环缓冲区(Circular Buffer),搜了些资料多数是基于循环队列的实现方式.使用一个变量存放缓冲区中的数据长度或者空出来一个空间来判断缓冲区是否满了.偶然间看到分析Linux内核的循 ...

  5. 【JS基础】循环

    for 循环的语法: for (语句 1; 语句 2; 语句 3) { 被执行的代码块 } 语句 1 在循环(代码块)开始前执行 语句 2 定义运行循环(代码块)的条件 语句 3 在循环(代码块)已被 ...

  6. 【python之路4】循环语句之while

    1.while 循环语句 #!/usr/bin/env python # -*- coding:utf-8 -*- import time bol = True while bol: print '1 ...

  7. To Java程序员:切勿用普通for循环遍历LinkedList

    ArrayList与LinkedList的普通for循环遍历 对于大部分Java程序员朋友们来说,可能平时使用得最多的List就是ArrayList,对于ArrayList的遍历,一般用如下写法: p ...

  8. JavaScript单线程和浏览器事件循环简述

    JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...

  9. .NET基础 一步步 一幕幕[循环、逻辑语句块]

    循环.逻辑语句块   好久不写博客了,断更了好几天了,从上周五到今天,从北京到上海,跨越了1213.0公里,从一个熟悉的城市到陌生的城市,还好本人适应力比较好,还有感谢小伙伴的接风咯,一切都不是事,好 ...

  10. Linux进程管理及while循环

    目录 进程的相关概念 进程查看及管理工具的使用 Linux系统作业控制 调整进程优先级 网络客户端工具 bash之while循环 20.1.进程类型 守护进程 daemon,在系统引导过程中启动的进程 ...

随机推荐

  1. 手机联系人信息获取(contacts) ---- HTML5+

    模块:contacts Contacts模块管理系统通讯录,用于可对系统通讯录进行增.删.改.查等操作.通过plus.contacts获取系统通讯录管理对象. 对象:联系人对象(属性:电话,地址等)针 ...

  2. 有关velocity的资料(等待整理)

    proxy-target-class="true" 与proxy-target-class="false"的区别: proxy-target-class属性值决 ...

  3. Redis讲解

    buffer  缓冲  用于写 cache  缓存  用于读 redis 支持持久化 安装redis yum -y install redis 配置文件/etc/redis.conf 是否在后台运行 ...

  4. 使用docx4j编程式地创建复杂的Word(.docx)文档

    原文链接:Create complex Word (.docx) documents programatically with docx4j 原文作者:jos.dirksen 发表日期:2012年2月 ...

  5. 使用CXF做webservice整合现有项目的例子

    从网上看了很多CXF的资料,大部分都是单独的作为一个webservice项目,对于在现有的spring项目上提供webservice服务的例子基本没有找到. 我做的这个例子是介绍怎么把cxf整合到现有 ...

  6. saml,sso

    saml,sso centos version get:// cat /etc/redhat-release

  7. Django - rest - framework - 下

    一.视图三部曲 https://www.cnblogs.com/wupeiqi/articles/7805382.html 使用混合(mixins) 之前得视图部分 # urls.py from dj ...

  8. (2.3)DDL增强功能-流程化控制与动态sql

    1.流程控制 在T-SQL中,与流程控制语句相关的关键字有8个: BEGIN...END BREAK GOTO CONTINUE IF...ELSE WHILE RETURN WAITFOR 其实还可 ...

  9. LVM的一些问题汇总 tune2fs命令

    LVM的一些问题汇总  tune2fs命令 --http://www.aminglinux.com/bbs/forum.php?mod=viewthread&tid=7664&page ...

  10. kafka详解

    一.基本概念 介绍 Kafka是一个分布式的.可分区的.可复制的消息系统.它提供了普通消息系统的功能,但具有自己独特的设计. 这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统术语:Kafk ...