r学习笔记第四篇:函数,分支和循环

悦光阴 悦光阴     2022-09-25     477

关键词:

变量用于临时存储数据,而函数用于操作数据,实现代码的重复使用。在R中,函数只是另一种数据类型的变量,可以被分配,操作,甚至把函数作为参数传递给其他函数。分支控制和循环控制,和通用编程语言的风格很相似,但是,不要因为R具有这些元素,就把R作为通用编程语言来看待,R的最小变量是向量,是一种面向数组(Array-Oriented)的语言。在编程时,尽量用array的方式思考,避免使用循环(for,while,repeat)控制,而使用apply函数家族实现计算的迭代,这是R语言的特色,把特定的函数应用于向量,列表或数组中的每个元素上。

一,R函数的风格

R通过function关键字定义函数,函数主要由函数名称,参数,运行的代码块和返回值组成,函数名称是变量,参数是调用函数时需要传递的形式参数;代码块是由由大括号构成,是调用函数时需要执行的代码逻辑;R的函数不需要显式地使用return关键字明确返回值,R函数的计算的最后一个值将自动作为返回值。

1,创建函数

例如,创建一个函数,并把函数赋值给avg变量,可以认为函数的名称是avg,其有两个参数a和b,大括号内的代码是函数体,实现的功能是求两个数的平均值。在R中创建函数时,如果函数体只有一行代码,可以省略大括号。

avg <- function(a,b)
{
    mead(c(a,b))
}

该函数没有显式调用return关键字,函数代码块种计算的最后一次自动最为返回值,在avg函数种,代码块调用系统函数mean,返回参数a和b的平均值,调用格式是函数名称(形式参数):

> avg(2,3)
[1] 2.5

调用函数时,如果不命名参数,则R按照位置匹配参数,因此,2对应形式参数a,3对应形式参数b。如果要改变传递参数的顺序,则可以传入命名参数:

> avg(b=2,a=3)
[1] 2.5

可以为函数的参数设置默认值,当调用函数时,如果没有为参数传递相应的值,那么函数将自动使用默认值作为函数代码块执行的当前值。

> avg <- function(a=1,b=1)mean(c(a,b))
> avg()
[1] 1

虽然函数中最后一行代码的值是自动返回的,但是,为了便于阅读代码,建议使用return函数,清晰地指定要返回的值,return函数除了指定函数的返回值之外,还能使函数退出,不再继续执行后面的代码。

> avg <- function(a=1,b=1) return(mean(c(a,b)))

2,把函数作为参数传递给其他函数

函数本质上是一个函数类型的变量,和其他类型的变量一样,能够作为函数的形式参数,传递给其他函数,例如:

> fn_call <- function(x,a,b)x(a,b)
> fn_call(avg,1,2)
[1] 1.5

R提供一个系统函数do.call(fun,args),用于调用其他函数,第一个参数是函数变量,第二个参数是有参数构成的列表:

> do.call(avg,args=list(1,2))
[1] 1.5

3,查看函数的定义

通过函数args用于显示函数的头部文本,用于显示函数的头部定义,例如:

> args(avg)
function (a = 1, b = 1) 
NULL

body(fun)函数用于返回函数的代码块,例如:

> body(avg)
mean(c(a, b))

除了这两个函数,还有函数formals(fun),用于查看函数的参数及其默认值,如果函数没有定义参数的默认值,那么只显示参数名,formals显示的参数名格式是$参数名。函数deparse(fun)用于查看函数调用的函数。

4,特殊的参数

R提供了一个特殊的运算符(...),该运算符允许函数具有任意多个的参数,并且不需要在函数定义中指定。

avg <- function(a,b, ...) mead(c(a,b))

二,分支控制

分支和循环是通用编程语言中必不可少的两大流程控制元素,分支控制是根据条件表达式的结果,执行不同的代码段。

1,if-else控制

经典的流程控制关键字是if-else,并可以把多个if-else语句连接到一起:

if ( test_expression1) {
statement1
} else if ( test_expression2) {
statement2
} else {
statement3
}

2,ifelse控制

ifelse控制是,在一个函数中,结合了if-else的功能,其语法是:

ifelse(test, yes, no)

当test条件为TRUE时,返回yes表达式的值,当test条件为FALSE时,返回no表达式的值。

> ifelse(c(1,2,3)>=2,'Greater','Less')
[1] "Less"    "Greater" "Greater"

对于ifelse的返回值,官方文档的描述是:

A vector of the same length and attributes (including dimensions and "class") as test and data values from the values of yes or no. The mode of the answer will be coerced from logical to accommodate first any values taken from yes and then any values taken from no.

注意:返回值的class属性跟test表达式相同,其mode属性是由 yes 或 no表达式确定的。

当ifelse()用于返回Date类型的对象时,返回值是numeric类型,而不是Date类型,这是因为返回值的class是由test表达式决定的。

dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)

解决方案是:把返回值的class重新设置为Date类型。

dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)
class(dates) <- 'Date'

3,switch函数

如果分支较多,可以使用switch函数实现分支的选择,switch函数的第一个参数是表达式(exp),通常是一个字符串;当表达式(exp)匹配后续的参数名(即变量名)时,返回参数的值:

> color <- function(t) switch(t,r='red',g='green',b='blue')
> color('r')
[1] "red"

如果不匹配任何参数名,switch函数不返回任何值,可以添加一个匿名的参数,当表达式(exp)匹配不上任意一个命名参数时,switch函数将返回匿名参数的值:

> color <- function(t) switch(t,r='red',g='green',b='blue', 'error')
> color('d')
[1] "error"

三,循环控制

循环控制是根据条件重复执行代码块,为了避免无限循环,可以根据条件结束循环。循环控制语句是repeat、while和for,R的向量化自带循环特性,减少了循环语句使用的场景,但是在重复执行代码时,循环控制还是非常有用。

1,repeat 循环

repeat 循环:先执行代码,遇到break关键字,结束循环,也可以在break关键字前增减if(test)语句,当指定的条件成立(为TRUE)时,执行break关键字,结束循环:

repeat {
code
if(test) break
}

2,while 循环

while 循环:先检测条件,如果条件为TRUE,执行code;如果条件为FALSE,结束循环:

while(test)
{
code
}

3,for 循环

for 循环:使用迭代器和一个向量参数,在每个循环中,迭代器变量从向量中取得一个值,直到迭代所有得向量:

for(i in c(1:5))
{
code
}

4,向量化的循环

R是向量化的编程语言,这使得R自身带有循环的特性,而不用使用循环控制语句。关于向量化的循环控制,请阅读我的博客文章

R语言学习 第九篇:plyr包

R语言学习 第十篇:操作符

 

 

参考文档:

How to prevent ifelse() from turning Date objects into numeric objects

pytorch学习笔记第四篇——神经网络(代码片段)

上一章已经了解了自动梯度Autograd,pytorch中可以使用torch.nn构建神经网络,nn依赖于autograd来定义模型并对其进行微分。nn.Module包含层,以及返回output的方法forward(input)。文章目录1.定义网络1.1自定义网络1.2使用自定义... 查看详情

第四篇:控制语句

控制语句有三种分支语句:if循环语句:while、repeat、for与程序转移有关的跳转语句:break、return 分支语句--if结构if表达式then    语句块(在表达式为真的时候得到执行)end--ifelse结构if表达式then语句块(在表达式为... 查看详情

学习笔记javascript基础

【学习过程遇到疑问和延伸阅读】 总结变量->数组代码块->判断分支执行->判断循环执行嵌套分支、嵌套循环的灵活运用分支类型-if,elseif,switchcase循环类型-while,do-while,for数组和对象联系区别成员vs对象原型对象vs... 查看详情

eclipse插件开发学习笔记pdf第一篇到第四篇免分下载开发基础核心技术高级进阶综合实例

<<Eclipse插件开发 学习笔记>>,本书由浅入深、有重点、有针对性地介绍了Eclipse插件开发技术,全书分为4篇共24章。第一篇介绍Eclipse平台界面开发的基础知识。包含SWT控件的使用、界面布局、事件处理等内容;第二... 查看详情

golang学习(用代码来学习)-第四篇

/**一个用来进行goroutine的函数*/funcprint_something(msgstring) fori:=0;i<5;i++ time.Sleep(1*time.Second) fmt.Println(msg) /**异步相加,并将结果放在通道中*/funcadd_async(aint,bint,ch*chanint) time.Sleep(2*time.Seco 查看详情

go语言入门教程系列——函数循环与分支

...公众号:TechFlow,原创不易,求个关注今天是Golang专题的第四篇,这一篇文章将会介绍golang当中的函数、循环以及选择判断的具体用法。函数在之前的文章当中其实我们已经接触过函数了,因为我们写的main函数本质上也是一个函... 查看详情

第三次实验计算分段函数第四次计算分段函数和循环new第五次分支+循环加强版实验报告

一.实验题目,设计思路,实现方法第四次分支+循环加强版(2-2计算个人所得税,2-7装睡,2-8计算天数)设计思路:2-2用if-else的语句,与计算分段函数的题类似的做法;2-7运用for语句依次进行呼吸频率和脉搏的比较;2-8运用数组... 查看详情

第四篇4.1章

break关键字可以用任何循环控制结构,从而使循环立即终止continue关键字可以用在任何循环控制结构中,它将导致循环立即跳到循环的下一个迭代中    在for循环中,continue关键字将导致控制流程立即跳到更新语句    在... 查看详情

第四篇[机器学习]机器学习,线性回归的优化

当我们的数据存在多重共线性时,即其中的一个自变量可以用其他一个或几个自变量的线性表达式进行表示,你会发现,拟合之后的方差会特别大一般说来当解释变量的容忍度(TOLERANCE)小于0.10或者方差膨胀因子(VIF)大于10时,说... 查看详情

django学习~第四篇

django表单  1 今天继续来学学django的表单    首先介绍下http的方法,这是最基本的    GET方法GET一般用于获取/查询资源信息,以?分割URL和传输数据,多个参数用&连接,login.action?name=hyddd&... 查看详情

#java学习之路——基础阶段二(第四篇)

我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容。前言:此随笔主要是J... 查看详情

git从青铜到王者第四篇:git的分支与合并(代码片段)

系列文章目录文章目录系列文章目录前言一、Git分支1.Git分支简介2.Git分支创建3.Git分支切换二、Git分支的新建与合并1.新建分支2.分支的合并3.遇到冲突时的分支合并三、分支管理四、分支开发工作流1.长期分支2.主题分支五、远... 查看详情

小白学习windows第四篇

一、用户帐户管理1、用户帐户不同的用户身份拥有不同的权限每个用户包含一个名称和一个密码用户帐户拥有唯一的安全标识符(SID)2、用户管理创建用户、为用户重置密码、重命名用户、启用、禁用用户帐户删除用户帐户(... 查看详情

小白入门深度学习|第四篇:配置pytorch环境

查看详情

python100天学习笔记day24js基本语法(代码片段)

JavaScript基本语法语句和注释变量和数据类型声明和赋值简单数据类型和复杂数据类型变量的命名规则表达式和运算符赋值运算符算术运算符比较运算符逻辑运算符分支结构if...else...switch...cas...default...循环结构for循环while循环do...... 查看详情

第四篇:docker安装并启动一个http容器

...就是:社区版是开源免费的,企业版是收费的。对于想要学习docker容器、或者小型开发团队来说,首选Docker社区版.1.卸载掉老版本的Docker容器yumremovedockerdocker-commondocker-selin 查看详情

第四章了不起的分支和循环[ddt书本学习小甲鱼]

4.4Python可以有效避免“悬挂else”Python的缩进使用强制规定使得代码必须正确对齐,else属于那个if清晰可见。4.5条件表达式(三元操作符) 代码ifx<y: small=x else: small=y 将以上代码用三元操作符来表示语法a=xif条件elsey含义:如... 查看详情

第四篇阅读笔记

   每个开发组都应该形成并制定一套工作习惯。在将大家集中在一起时,首先制定一份粗略的系统功能图,方便大家对于该系统形成一个统一的共识,制定详细的用例视图。        用例的来源庞... 查看详情