前两天 dapeng 用 R 给师妹做了一张”全国各省 PM10 浓度地图”,以省会城市的 PM10 浓度值给各省涂上颜色,结果师妹说:这个用 ArcGIS 能又快又好地做出来。 dapeng 脑子里立刻涌现出多种说法要细数 R 的优势,第一条就是:若是有 20 年的数据,每年做一张图,R 菜鸟用简单一个循环就能编程搞定,ArcGIS 该怎么又快又好做出来?若不是资深用户的话,我等菜鸟恐怕得一张一张图点出来吧?这种操作费时费力并且毫无乐趣,就应该交给机器来解决,这是懒人的必备技能。本篇就来说说程序的基本结构之一:循环。
开胃小菜 男人至少要擅长一项运动,一种乐器,一种编程….和拿手的几个小炒. (语出小鸟学AHK)
所谓循环,就是兜圈子,就是一件事情重复操作。先从一个简单例子开始。在第 03 篇中,我们对 8 米和 100 米两个高度处测量的 PM2.5 做了日变化图。若要对三个高度的每一个都做日变化图,不用循环,那么是这样的:
pm <- read.csv(file = "c:\\R\\data\\dapengde_DummyR_PM25.csv")
par(mfrow=c(1, 3))
plot(pm[, 1], pm[, 2], cex = 2, type = "l") # 第一张图
plot(pm[, 1], pm[, 3], cex = 2, type = "l") # 第二张图
plot(pm[, 1], pm[, 4], cex = 2, type = "l") # 第三张图
如果使用循环,是这样的:
par(mfrow=c(1,3))
for (i in c(2, 3, 4)) plot(pm[, 1], pm[, i], cex = 2, type = "l") # 让 i 的取值在2, 3, 4这三个数中转一圈,做第 i 张图。
这里出现的 for()
就是循环语句。看起来跟不用循环也差不多嘛。是的。但是有一次 dapeng 要给 20 个观测点 一个月的 PM2.5 每天做一张日变化图来,总共要做 600 张,要是不用循环,那恐怕连死的心都有了。话说 dapeng 当年第一次接触计算机程序的时候,就为循环语句兴奋得睡不着觉,那种久旱逢甘露感觉记忆犹新。懒人福音啊!
i
转的那个圈,可以是数字,也可以是别的,比如字符串:
for (i in c("Good", "Morning", "!")) print(i)
练习05.1 用`print()` 指令打印 1 到 100 之间的奇数。
R 中常用的循环语句,除了 for()
之外,还有while()
和 until()
,相互之间可以换用。
下面我们用循环语句来做一个指数增长模型,再体会一下循环的意义。
指数增长模型,也叫马尔萨斯增长模型,一个函数的增长率与其函数值成比例。举个例子吧,我们用 N1
表示 2008 年世界总人口 66.8 亿,r 表示人口自然增长率,为简化起见假定 r
是个常数 0.011,那么在下一年的总人口就是 N2 = N1 + r * N1
。我们想看看今后一百年的人口总数,可以这样做:
# 方法 1:每年分别计算,分别存储人口数。
N1 <- 66.8
r <- 0.011
N2 <- N1 + r * N1
N3 <- N2 + r * N2 # 如此一直写到 N100。
# 方法 2:每年分别计算,用一个向量来存储各年人口总数。
N <- numeric(100)
N[1] <- 66.8
N[2] <- N[1] + r * N[1]
N[3] <- N[2] + r * N[2] # 如此一直写到 N[100]。
# 方法 3: 用循环语句计算,用一个向量来存储各年人口数。
N <- numeric(100)
N[1] <- 66.8
for (t in 1:99) N[t + 1] <- N[t] + r * N[t] # 不必一直写到N100。
plot(N)
循环的好处一览无余!
上面的例子里,每次重复的操作只有一条指令,所以直接写在 for () 后面就可以了。实际遇到的情况往往是重复一组指令,比如 每次给 N[t+1] 赋值时想显示一下当年人口和年份,那么可以用花括号把一组指令组合起来:
for(t in 1:99)
{
N[t+1] <- N[t] + r * N[t]
print(t + 2007)
print(N[t+1])
}
到目前为止,R 中所有的括号都闪亮登场了一遍,这里小结一下它们的角色:
- 圆括号 ()。用作命令和数学表达式,如
mean(x), (1 + 2) * 3
。 - 方括号 []。用作下标,调用向量中的某个元素,如
x[3], pm[2,6]
。 花括号 {}。用作编程,把一组指令组合在一起,如
for () {}
。练习05.2 生成一个矩阵 m (方法见 matrix 函数的帮助信息),使得 m[i,j] = x[i] * y[j], 其中 x <- c(2, 3, 5), y <- c(1, 2, 3, 4)。
有用的信息:
– | – |
---|---|
循环语句 | for(), while(), until() |
括号的用法 | () [] {} |
( 连载中,待续 )