变量用于临时存储数据,而函数用于操作数据,实现代码的重复使用。在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.5

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

> avg(b=,a=)
[] 2.5

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

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

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

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

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

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

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

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

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

3,查看函数的定义

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

> args(avg)
function (a = , b = )
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(,,)>=,'Greater','Less')
[] "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 - , 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 - , dates)
class(dates) <- 'Date'

3,switch函数

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

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

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

> color <- function(t) switch(t,r='red',g='green',b='blue', 'error')
> color('d')
[] "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(:))
{
code
}

4,向量化的循环

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

R语言学习 第九篇:plyr包

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

 

参考文档:

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

R学习笔记 第四篇:函数,分支和循环的更多相关文章

  1. python学习笔记(四)之分支和循环

    python中比较操作符有: > >= < <= == != 这些操作符返回True或False 1 >>> 1 < 3 2 True 3 >&g ...

  2. python3.4学习笔记(十) 常用操作符,条件分支和循环实例

    python3.4学习笔记(十) 常用操作符,条件分支和循环实例 #Pyhon常用操作符 c = d = 10 d /= 8 #3.x真正的除法 print(d) #1.25 c //= 8 #用两个 ...

  3. R学习笔记 第三篇:数据框

    数据框(data.frame)用于存储二维表(即关系表)的数据,每一列存储的数据类型必须相同,不同的数据列的数据类型可以相同,也可以不同,但是,每列的长度必须相同.数据框的每列可以有唯一的命名,在已创 ...

  4. R学习笔记 第五篇:数据变换和清理

    在使用R的分组操作之前,首先要了解R语言包,包实质上是实现特定功能的,预先写好的代码库(library),R拥有大量的软件包,许多包都是由某一领域的专家编写的,但并不是所有的包都有很高的质量的,在使用 ...

  5. R学习笔记 第五篇:字符串操作

    文本数据存储在字符向量中,字符向量的每个元素都是字符串,而非单独的字符.在R中,可以使用双引号,或单引号表示字符,函数nchar用于获得字符串中的字符数量: > s='read' > nc ...

  6. Django学习笔记第四篇--数据处理URL和数据库

    一.URL: 1.基础的URL与视图函数的映射 from django.conf.urls import url from django.contrib import admin from appna ...

  7. python学习笔记(四)— 函数

    一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或子程序),在Pasc ...

  8. objective-C学习笔记(四)函数成员:方法(函数)

    函数分为:  全局函数(C语言函数) 成员函数(OBJC方法):实例方法 “-” 和类方法“+”的区别 //这里要区别静态变量(类变量).全局函数.常量的区别 OBJC里面,所有方法默认为公有方法.没 ...

  9. Asp.net core Identity + identity server + angular 学习笔记 (第四篇)

    来说说 RBAC (role based access control) 这是目前全世界最通用的权限管理机制, 当然使用率高并不是说它最好. 它也有很多局限的. 我们来讲讲最简单的 role base ...

随机推荐

  1. java的Date类和TimeStamp类

    Java API中有两个Date类,一个是java.util.Date,其构造方法如下: Date() Date(long date) 主要方法有: boolean after(Date when) ...

  2. 关于sublime3的使用

    一.安装Package Control 使用Ctrl+`快捷键或者通过View->Show Console菜单打开命令行,粘贴如下代码: import urllib.request,os; pf ...

  3. 浅析Spring MVC工作机制

    1.如何使用Spring MVC? 在web.xml中配置一个DispatcherServlet DispatchServlet初始化的时候会去寻找一个在应用程序的WEB-INF目录下的配置文件,命名 ...

  4. java集合系列——Map之HashMap介绍(八)

    1.HashMap的简介 (JDK1.7.0_79版本) HashMap是基于哈希表的Map实现的的,一个Key对应一个Value,允许使用null键和null值,不保证映射的顺序,特别是它不保证该顺 ...

  5. canvas,html2canvas等合成图片不清晰问题

    function  pxRa(cxt) { var backingStore = context.backingStorePixelRatio || context.webkitBackingStor ...

  6. Lowbit Sum 规律

    Lowbit Sum Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitSt ...

  7. 郑厂长系列故事——排兵布阵 hdu4539(状态压缩DP)

    郑厂长系列故事——排兵布阵 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)To ...

  8. MyBatis Generator代码自动生成工具的使用

    MyBatis Generator MyBatis Generator有三种使用方式,分别是maven插件形式.命令行形式以及eclipse插件形式.我在这里使用的是命令行的形式(主要是命令行形式比较 ...

  9. Nginx 1.10.1 版本nginx.conf优化配置及详细注释

    Nginx 1.10.1 的nginx.conf文件,是调优后的,可以拿来用,有一些设置无效,我备注上了,不知道是不是版本的问题,回头查一下再更正. #普通配置 #==性能配置 #运行用户 user ...

  10. DotNetCore跨平台~一起聊聊Microsoft.Extensions.DependencyInjection

    写这篇文章的心情:激动 Microsoft.Extensions.DependencyInjection在github上同样是开源的,它在dotnetcore里被广泛的使用,比起之前的autofac, ...