R 菜鸟入门篇 第06篇 分支

顺序、循环和分支是编程的三大结构。上一篇说了循环,这一篇说说分支。啥是分支?分支就是你到了一个路口,向左向右向前看,要选择到底往哪个方向走。每时每刻我们都要做出选择:渴了,是喝咖啡还是茶?见了人,是上去打招呼还是悄悄躲开?这篇帖子,是关掉还是继续读下去?其实仔细想想,岂止是编程,那三大结构简直就是整个生活的基本结构:日出日落,月圆月缺,年尾年头,这是循环;上学还是就业,单身还是结婚,丁克还是生娃,这是分支;不管是循环还是分支,都嵌入在生老病死的时间轴上,这是顺序。所谓尽人事听天命,想来就是心平气和地接受顺序结构,小心翼翼地制订循环结构,在关键时刻控制好分支结构,就这样度过一生罢。

扯远了。简单来说,分支就是先判断再选择。

先判断。判断要用逻辑运算。我们先来做一套健脑操热热身:

3 > 2  # 3比2大吗?是的。
## [1] TRUE
1 > 2  # 1比2大吗?不是的。
## [1] FALSE
!(1 > 2)  # 1不比2大吗?呃......
## [1] TRUE
3 > 2 & 1 > 2  # 3比2大,并且1比2大吗?不是的。
## [1] FALSE
3 > 2 | 1 > 2  # 3比2大,或者1比2大吗?是的。
## [1] TRUE
3 > 2 & !(1 > 2)  # 3比2大,并且1不比2大吗?好像是吧......
## [1] TRUE

好了,热身完毕。包括上面出现的,常用的逻辑运算符有:大于 >, 小于 <, 等于 ==, 小于或等于 <=, 大于或等于 >=, 与 &, 非 !, 或|

逻辑运算符用在向量上:

x <- 1:3
x == 2
## [1] FALSE  TRUE FALSE
x == 2 | x == 3
## [1] FALSE  TRUE  TRUE
y <- c(4, 1, 2)
x > y
## [1] FALSE  TRUE  TRUE
x > y & y > 1
## [1] FALSE FALSE  TRUE
练习06.1 设 x <- 6:1,y <- c(3, 5, 7),判断 x 中的每个元素是否在y中出现。

上面这个练习可以用循环来完成。不过,由于 R 很照顾懒人,所以提供了更方便的方法:

x %in% y
## [1]  TRUE  TRUE FALSE

结合逻辑判断和下标系统,就可以挑出 x 中哪些元素出现在 y 中,以及出现的位置:

x[x %in% y]
## [1] 1 2
which(x %in% y)
## [1] 1 2
练习06.2 从 1:100 中挑出既能被 2 整除,又能被 3 整除的数(提示:判断整除的余数是否为零)。

下面,我们玩玩真实的观测数据。练习01.4 曾经提出个问题:PM2.5 一天中的最大值出现在几点钟?当时需要肉眼判断,现在可以交给机器了。

pm <- read.csv("c:\\R\\data\\dapengde_DummyR_PM25.csv")
pm$time[which(pm$h8 == max(pm$h8))]
## [1]  8  9 10
练习06.3 世界卫生组织制订的 PM2.5 指导标准中最宽松的标准是 24 小时均值 75 微克每立方米。请挑出北京一天内超出此标准的时段。

上面讲的是分支两部曲的第一步:判断。下面说说第二步:选择。

x <- 12
if (x < 99) print("x is less than 99")  # 如果(),那么。
## [1] "x is less than 99"

x <- 12
if (x < 99) {
    print("x is less than 99")
} else {
    print("x is larger than 99")
}  # 如果(),那么{},否则{}。
## [1] "x is less than 99"

x <- 12
ifelse(x < 99, "small", "large")  # 等同于上一个例子,不同的是这里 x 的向量长度可以大于1,比如试试 x <- 98:100。
## [1] "small"

有了分支语句,就可以在很多地方派上用场了。继续以北京 PM2.5 日变化数据作图,把一天中的最大值重点标出来,然后把达标值用绿色区分出来:

plot(x = pm$time, y = pm$h8, xlab = "Time", ylab = "PM2.5", cex = ifelse(pm$h8 == 
    max(pm$h8), 2, 1), pch = 16, type = "b", col = ifelse(pm$h8 > 75, "red", 
    "darkgreen"))

plot of chunk unnamed-chunk-7

有用的信息:

逻辑运算 > < == <= >= & !
分支命令 if () {}, if () {} else {}, ifelse()

( 连载中,待续 )

R 菜鸟入门篇 第06篇 分支》上有15条评论

      1. 卡卡

        x[x %in% y]的结果应该是5 3吧?

        which(x %in% y)的结果应该是2 4吧?

        回复
  1. yaoyx001

    又来打扰了。 最后那幅图,如何改变线的颜色呢? (比如从红色到蓝色)。 因为符号填充色和线色都是用col 来定义的,有些糊涂了。先谢谢dapeng。

    回复
    1. 大鹏 文章作者

      可以用一条point()语句添加红色的点,再用另一条point()语句添加蓝色的线。

      回复
    1. 大鹏 文章作者

      Yihui:R的竞争对手已经不是SAS,而是Python,我对此表示完全同意。如果R核心团队能有更开放的态度,也许还有希望和Python在统计领域一搏,毕竟有强大的先发优势,但如今我们只能面对Python神教的不断奚落去曲线救国,R本身我们动不了,只能从R包入手。

      回复
  2. RICCI

    **> (6:1)==c(3,5,7)

    [1] FALSE TRUE FALSE TRUE FALSE FALSE**

    也可以用==,不需要用%in%?

    回复
    1. 大鹏 文章作者

      哈哈哈,这个例子太有趣了。试比较 (1:6) == c(3,5,7)(1:6) %in% c(3,5,7)

      回复
  3. jojocat

    大鹏,能不能附个练习的答案呢?你有邮箱吗?可以发邮件给你不?

    回复
    1. 大鹏 文章作者

      答案可以有,但是没必要,而且不重要。可以发邮件给我,dapengde(at)live.com

      回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax