logo

您的位置:首页 > 新闻资讯

回忆杀:鸡兔同笼的R实现——if else使用指南

前言

小伙伴们,我胡汉三又回来啦。

同学们还记得小时候的鸡兔同笼问题吗?

一个笼中有几只脚,抓出来几只后还有几只脚,问:分别有几只鸡几只兔?

小时候常常想不明白,为啥要把小鸡和小兔关在一个笼子里呢,它们的生活习性完全不同嘛——小鸡吃小米,小兔吃青菜。

今天我们就借鸡兔同笼的小米青菜问题,来聊一聊if else的R实现。

胖瘦兄弟if else和ifelse

在讲鸡兔同笼的喂食问题前呢,我们还是先看一下这次的主角 if else,和它的瘦版小弟ifelse。

在R语言里,if else与ifelse可以说是根出同处,花开两支。尽管只有一个空格的差距,它们的使用对象、编程方法并不相同。

具体的说,它们核心算法是一样的,都对某一对象进行条件判定和命令执行;但是,在应用对象和编程语言结构上,两者完全不同。

胖大哥if else是对单个对象执行这套程序,瘦小弟ifelse是对一串对象执行这套程序。用标准统计语言来讲, ifelse是向量化版的if else。

看着有点绕是不是?没关系,下面我们会有很多例子来说明这两者的应用方法。

二元条件判定-是鸡还是兔

问:人生中最大的问题是神马?
答: 不是to be or not to be,而是今天晚上吃啥。

人是这样,动物也是这样。你不能强迫小兔吃小米(不,华为也不行),也不能强迫小鸡吃青菜。

那么,如果我们一定要把小鸡和小兔关在一个笼子里,吃饭的问题应该怎样解决呢?

按正常的思路,肯定是抓住一只动物,看看它是什么,是小鸡就喂小米,不是就喂青菜。

对头,整个流程就是这样:


图片一:二元条件判定流程图

if else就是一个条件判断并执行命令的组合。刚才我们的鸡兔同笼喂食问题,在R中就可以写成:


图片二:if else二元代码

小伙伴们注意,以上的鸡兔同笼问题,我们只涉及到两种情况,即条件判断的结果只有两种,一组if else命令即可以覆盖全部的可能性。因此,在二元问题中,无论对哪个条件进行判断,都会得出相同的结果。


图片三:if else代码第二种写法

在这里,我们就可以通过简化版的胖大哥if else命令写法,引出瘦小弟ifelse的写法。

ifelse,占地面积很小,一行就够。它删去了{}引导的执行部分,而在自身()中就体现出了两个不同条件下的命令。同时,我们上文提到, ifelse是对一串数据进行判断。在这个问题中,我们可以理解为对笼子里的每一只动物进行逐一判定。

那么,我们给出笼子内动物的集合,并用瘦小弟ifelse代码把喂食方法写出来,就是:


图片四:ifelse二元代码

可以看到, ifelse是把要判断的条件放在()内第一项,把该条件满足时需要执行的命令放在第二位,把该条件不满足时需要执行的命令放在第三位,这三者间用逗号隔开。

对于简单问题,瘦版ifelse更简便一些。同时,推荐小伙伴们熟练掌握胖版if else标准用法,因为在复杂问题中以及在与apply、for loop结合的情况下,标准if else用法逻辑更清晰。

多元判定-小鸡、小白兔与小灰兔

之前我们说把小鸡和小兔关在一个笼子时的喂食问题。现在我们把这个问题想得复杂一些:在这个笼子里同时关着两种颜色的兔子—白兔和灰兔,我们要对着两种兔子区别喂食—白兔喂胡萝卜,灰兔喂青菜。

这个笼子的动物与食物关系就变成了:


图片五:多元鸡兔同笼问题示意

当我们用if else命令实现这一构想时,我们写成:


图片六:多元条件判定if else写法

和二元判断一样,多元判断中条件的顺序并不影响结果。我们可以把任意一个条件写在前面。此处就不再示范啦。

我们可以抽象出多层条件判断的流程图:


图片七:多层条件判断流程图

可以看到的是,最后一个条件是不需要判定的(因为此时其它条件已被排除)。因此如果条件—命令总数为n个,在if else结构中,if 引导的条件判断部分有n-1个,{}引导的命令执行部分为n个。

那么多层条件判断中可不可以用瘦小弟ifelse呢?可以的,而且有不只一种写法。这里介绍给小伙伴们一个看起来最清晰的写法,简称ifelse套娃法。

在我们这里假设的三种可能(三个条件)的情况下,逻辑链是:ifelse(condition1, yes1, ifelse(condition2, yes2, no))。

注意,和胖版if else 命令一样,在三种可能的情况下,我们只需要针对条件判断两次,因此出现了condition1和condition2。同时,在condition1被满足时需要执行第一命令,即yes1;在condition2被满足时需要执行第二命令,即yes2;在condition2不被满足时,我们已排除所有其它可能,那么一定是condition3被满足,我们执行此时的no其实是yes3。

小白兔问题在R中写出来即是:


图片八:多元判定ifelse写法

如果在实际分析中遇到n个条件需要判断,那么ifelse是在内部从第1个条件开始套到第n-1个条件,并在前n-2个条件后都跟有条件符合时需要执行的命令,在最后n-1条件下,跟有条件符合及不符合情况下需要执行的命令。

R中实战

在实际应用中,比较常见的分组问题是年龄的分组。那么我们来演练一下,应该怎样使用if else兄弟命令。

首先,我们先定义一下年龄:


图片九:生成随机年龄分布

接下来,我们看一看简单二元判定。我们以50岁为界,划分50岁以内为第1组,50岁以上为第2组。

前文我们提到过, if else是对单个对象的命令。那么在对全部30个年龄进行划分时,我们该怎么办呢?

敲黑板!!上次我们讲过apply三兄弟系列(想不起来的小伙伴们偷偷地戳这里:此处请插入之前apply文章)。

这里我们可以将if else写为一个程序,同时利用sapply将此程序应用在完整的数据群上。


图片十:if else与sapply联用二元分组代码

当然了,我们也可以用简化版的ifelse,一行代码搞定:


图片十一:ifelse二元分组代码

现在,我们要把年龄分为四组,分别以25岁,35岁,45岁,55岁为年龄分界点。

注意,现在出现了一个新的问题,在25-35岁、35-45岁、45-55岁这三组出现了“考察对象同时满足两个条件”的情况(例如在25-35岁组,需要同时满足年龄大于25岁且小于35岁)。

这一情况在R中如何处理呢?

不要怕!还记得R中表示“并且”的是哪个符号吗?没错,就是“&”。我们无论在if else 或ifelse中都可以使用“&”,从而得到同时满足两个条件的数据。

那先来看一下胖大哥if else应该如何编码:


图片十二:if else双条件满足情况多元问题代码

在瘦小弟ifelse中,也是相似的格式:


图片十三 ifelse双条件满足多元问题代码

以上,就是胖胖if else与瘦瘦ifelse的使用指南,小伙伴们学会了吗?有问题欢迎给我们留言哦。

后文预告:初学者三杰中的for loop接下来就要出场啦,欢迎关注。另外接着来一波广告,想听自定义函数的小伙伴们快点举手呀,只要998,只要998,自定义函数带回家~




微信扫一扫
关注该公众号

最新课程

ABOUT US

克里克学院是一家致力于组织生命科学及医学领域科研及应用培训的专业机构
我们的宗旨是,打破高校壁垒,遍请天下名师!

Contact information

邮编:200000
电话:+86-21-67620569
传真:+86-21-67620569

网址:www.crickcollege.com
邮箱:marketing@crickcollege.com
地址:上海市松江区沪松公路1399弄69号717-718室

Copyright 2016 crickcollege. All rights reserved.