R语言编程艺术(3)R语言编程基础
本文对应《R语言编程艺术》
第7章:R语言编程结构;
第9章:面向对象的编程;
第13章:调试
=========================================================================
R语言编程结构
控制语句:
循环:
for (n in x) { } while (condition) { } repeat { }
另外break也可以用在另两种形式的循环语句中。注意repeat没有跳出循环的判断条件,因此使用break(或者类似return())的语句。
除此之外,next语句可以用来跳过本次迭代的剩余部分。具体应用情景,是可以替代循环中的条件嵌套语句,不致代码看起来混乱。
需要注意的是,for结构可以用在任何向量上,无论向量是什么模式,注意灵活运用。
对非向量集合的循环:R并不支持直接对非向量集合的循环,但是有一些间接但简单的方式可以做到这点:
使用lapply()。如果循环的每次迭代之间相互独立,就是用lapply(),可以允许以任意顺序执行;
使用get()。这个函数接受一个代表对象名字的字符串参数,然后返回该对象的内容,看起来简单,但是十分有用。
#假设u, v都是两列的矩阵,要分别在这两个矩阵上应用lm函数 for (m in c(“u”, “v”)) { z <- get(m) print(lm(z[, 2] ~ z[, 1])) }
if-else结构:
#注意以下代码 if (r == 4) {x <- 1 } else {x <- 3y <- 4 }
虽然if后面只有一条语句,但是它对应的大括号是不能省略的,原因在于R的解释器是根据else前面的右括号判断这是一个if-else结构,如果没有大括号,R将认为这是一个if结构。
#if-else结构的简化 v <- if (cond) expression1 else expression2
这是一个简化代码的技巧,因为if-else结构最终会返回的值取决于cond是否为真。如果expression是函数调用语句,可以让代码更为清晰,但是如果语句复杂,就要优先考虑代码是否清晰易懂。
处理向量时,使用向量化的ifelse()函数有可能提高运行速度。
算术和逻辑运算符及数值:
之前提到,R中只有向量,没有标量,标量可以看作是仅有一个值的向量。但是在逻辑运算时,特别是if语句的条件控制,其逻辑值不能为向量,只能有一个值,也就是可以看作标量。这时,就要区分逻辑与和逻辑或的向量标量运算了。
x && y |
标量的逻辑与运算 |
x || y |
标量的逻辑或运算 |
x & y |
向量的逻辑与运算 |
x | y |
向量的逻辑或运算 |
如果if语句里的控制条件里出现向量并且长度大于1,R的处理方式是将向量的第一个元素作为控制条件返回结果,然后提示warning message
参数的默认值:
具名实参(named argument):如果不使用默认值,那么在调用函数时必须给出参数的具体名称;
惰性求值(lazy evaluation)原则:除非有需要,否则不会计算一个表达式的值,也就是说具名实参不一定会被使用。
返回值:
函数的返回值可以是任何R对象。通常为列表形式,但是如果有需要,甚至可以返回另一个函数。
一般来说,如果只在函数结尾返回值,要避免显式地调用return()函数。如果想要将程序表达得更加清晰,在函数中间部分返回值的时候可以显式地调用return()函数。
返回复杂对象:函数的返回值可以是另一个函数。如果函数需要返回多个返回值,可以把它们储存在一个列表或其他容器变量中。
函数都是对象:
注意到函数是对象,也就是说对于对象的操作对函数也适用。包括创建、编辑,甚至在以函数组成的列表上做循环。
g <- function(h, a, b) h(a, b) body(g) <- quote(2 * x + 3) g(3) # 9
首先,function函数创建了一个函数,并赋值给g;然后body函数修改了g的函数体。因为函数主体部分属于”call”类,而这种类是由quote()函数生成。
环境和变量作用域的问题:
顶层环境:<environment: R_GlobalEnv>
变量作用域的层次:里层的函数可以使用更加顶层的变量,如果层次之间变量命名发生冲突,优先使用最里层的变量。一般来说,里层对于更加顶层的变量只读不可写。可写的情况将单独讨论。
ls()函数:调用不带参数的ls()可以返回当前的局部变量;使用envir参数可以返回函数调用链中任何一个框架的局部变量名。
函数代码对于其非局部变量一般只读不写,即使重新赋值也是影响它们的备份而不是变量本身。事实上,直到局部变量发生变化前,与其对应的全局变量是共享一个内存地址的。
R语言中没有指针:
不能直接改变一个函数的参数,只能重新赋值。
其他因为没有指针造成的问题将在下文讨论。
向上级层次进行写操作:
利用超赋值运算符对非局部变量进行写操作:<<-
注意,超赋值运算符进行写操作的时候,首先逐层向上级环境层次查找,遇到该变量的第一个层次即进行操作,如果没有遇到,将在全局层次上新建变量。
用assign()函数对非局部变量进行写操作:
可以通过设置函数参数指定向上层的哪一层次的变量进行写操作。注意引用变量是使用字符串实现的。
全局变量的使用:一般来说不推荐在函数中写全局变量,但是有时为了简化代码,这么做也是可以的,灵活运用即可。对于大型程序不推荐这样做,因为存在着重写不相关却同名变量的风险。一种折中的方案是,在顶层环境中新建一个封装全局变量的包,再使用assign()和get()函数通过索引到这个包来访问全局变量。
闭包:这里的闭包指一种编程方法,具体做法是,先定义一个可创建局部变量的函数,再创建另一个函数可以访问该变量。这样,后面的一些函数创建的局部变量之间互不影响,各自独立。
递归:
用于回归和分类的递归分块方法库:rpart
置换函数:
任何左边不是标识符(意味变量名)的赋值语句都可看作是“置换函数”。当遇到以下形式:
g(u) <- v
R语言会尝试用以下方式执行:
u <- “g<-”(u, value = v)
直观感受下,就是将值赋值给函数调用的结果。事实上,只要左边不是变量名,就是一个置换语句,比如u[2] <- 8
写函数代码的工具:
快速载入环境:
source(“filename.R”)
编辑函数:
f1 <- edit(f1) f2 <- edit(f1)
创建自己的二元运算符:
> “%a2b%” <- function(a, b) return(a + 2 * b) > 3 %a2b% 5 [1] 13
匿名函数:
如果函数不是很复杂,可以省去函数定义的过程,在使用function()命令建立函数后直接调用,因为没有具体的函数名,因此称为匿名函数。应用情况取决于具体情况,可以使代码更加易读紧凑。
=========================================================================
面向对象的编程
- 能接触到的R中所有东西(从数字到字符串到矩阵)都是对象
- R支持“封装”(encapsulation),即把独立但相关的数据项目打包为一个类的实例。封装可以帮助你跟踪相关的变量,提高清晰度
- R类是“多态”(polymorphic)的,这意味着相同的函数使用不同类的对象时可以调用不同的操作。多态可以促进代码可重用性
- R允许“继承”,即允许把一个给定的类的性质自动赋予为其下属的更特殊化的类
S3类:
一个S3类包含一个列表,再附加上一个类名属性和调度(dispatch)的功能。
S3泛型函数:即同一个函数可以针对不同的类调用不同的操作。可以通过method()函数找到给定泛型函数的所有实现方法,返回值中,星号标注的是不可见函数(nonvisible function),即不在默认命名空间中的函数,可以通过getAnywhere()函数找到这些函数。另外可以查看一个类能应用的所有泛型函数,代码method(, class = “classname”)
编写S3类:“类”属性可以通过attr()或class()函数手动设置。然后可以针对自己编写的类,设定独有的泛型函数,下面是一个例子:
#创建一个名为employee的类的对象 j <- list(name = “Joe”, salary = 55000, union = T) class(j) <- “employee” #编写类employee的打印方法 print.employee <- function(wrkr) {cat(wrkr$name, “\n”)cat(“salary”, wrkr$salary, “\n”)cat(“union member”, wrkr$union, “\n”) }
使用继承:继承的思想是在已有类的基础上创建新的类:
#创建类employee的子类hrlyemployee k <- list(name = “Kate”, salary = 68000, union = F, hrsthismonth = 2) class(k) <- c(“hrlyemployee”, “employee”)
新类包含了两个字符串,分别代表新类和原有的类,新类继承了原有类的方法,可以使用对应的泛型函数。泛型函数在调度时的工作原理是首先查找两个类名称的第一个,如果没查到,则再去查找第二个类,实现了继承。
S4类:
操作 |
S3类 |
S4类 |
定义类 |
在构造函数的代码中隐式定义 |
setClass() |
创建对象 |
创建列表,设置类属性 |
new() |
引用成员变量 |
$ |
@ |
实现泛型函数f() |
定义f.classname() |
setMethod() |
声明泛型函数 |
UseMethod() |
setGeneric() |
编写S4类:
> #定义类employee > setClass(“employee”, + representation( + name = “character”, + salary = “numeric”, + union = “logical”) + )[1] “employee”> #创建一个类的实例 > joe <- new(“employee”, name = “Joe”, salary = 55000, union = TRUE) > joeAn object of class “employee”Slot “name”:[1] “Joe”Slot “salary”:[1] 55000Slot “union”:[1] TRUE> #引用成员变量 > joe@salary[1] 55000> slot(joe, “salary”)[1] 55000> #赋值也可以使用这两种方法 > joe@salary <- 88000 > slot(joe, “salary”) <- 88000
S4类的安全性在于,如果给不存在的成员变量赋值,会有报错消息,而S3类将会新建一个成员变量。
> joe@salry <- 48000Error in checkSlotAssignment(object, name, value) :“salry” is not a slot in class “employee”
在S4类上实现泛型函数:
#show()函数指在交互模式下,输入变量名直接打印 setMethod(“show”, “employee”, function(object) {inorout <- ifelse(object@union, “is”, “is not”)cat(object@name, “has a salary of”, object@salary,"and", inorout, "in the union", "\n") } )
S3类和S4类的对比:
S3具有较强的灵活性,而S4具有很好的安全性。一般来说推荐使用S3使代码更加灵活,而当安全性更加重要时选择S4(比如混合编程的情况下)。
对象的管理:
ls()函数:列出所有对象;
rm()函数:删除特定对象;
save()函数:保存对象集合,可以用load()载入;
查看对象内部结构的函数:class(), mode(), names(), attributes(), unclass(), str(), edit();
exists()函数:判断对象是否存在。
=========================================================================
调试
调试的基本原则:
调试的本质:确认原则;
从小处着手;
模块化的、自顶向下的调试风格;
反漏洞。
转载于:https://www.cnblogs.com/gyjerry/p/6530099.html
R语言编程艺术(3)R语言编程基础相关推荐
- 程序员编程艺术第一~三十八章集锦与总结,及Github地址、PDF下载
程序员编程艺术第1~38章集锦与总结,及Github.PDF下载 前言 熟悉本blog的朋友大都知道,在2010年刚开始写本博客之际,我整理过一个微软面试100题,后来我为这100题开始发帖讨论,写答 ...
- 程序员编程艺术第一 三十八章集锦与总结,及Github地址 PDF下载
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 程序员编 ...
- R语言编程艺术(1)快速入门
这本书与手上其他的R语言参考书不同,主要从编程角度阐释R语言,而不是从统计角度.因为之前并没有深刻考虑这些,因此写出的代码往往是一条条命令的集合,并不像是"程序",因此,希望通过学 ...
- R语言编程艺术(4)R对数据、文件、字符串以及图形的处理
本文对应<R语言编程艺术> 第8章:数学运算与模拟: 第10章:输入与输出: 第11章:字符串操作: 第12章:绘图 =================================== ...
- 《R语言编程艺术》——1.4 R语言中一些重要的数据结构
1.4 R语言中一些重要的数据结构 R有多种数据结构.本节将简单介绍几种常用的数据结构,使读者在深入细节之前先对R语言有个大概的认识.这样,读者至少可以开始尝试一些很有意义的例子,即使这些例子背后更多 ...
- r intersect()_30分钟掌握R语言编程基础
R语言是世界上最广泛使用的统计编程语言.本文的目的是使得读者快速上手R语言编程. 1 R语言概述 R语言是世界上最广泛使用的统计编程语言.有人认为,它是数据科学家的第一选择(人生苦短,我选Python ...
- r语言软件GDINA_finTech MSc代做、代写Python程序语言、代写MSc program、代做Python设计帮做C/C++编程|代写R语言...
finTech MSc代做.代写Python程序语言.代写MSc program.代做Python设计帮做C/C++编程|代写R语言Strathclyde Business School, finTe ...
- 【编程实践】第二章 C++面向对象编程《C++程序设计语言》 / By 禅与计算机程序设计艺术ChatGPT
[编程实践]第二章 C++面向对象编程<C++程序设计语言> / By 禅与计算机程序设计艺术&ChatGPT 第二章 C++面向对象编程 在C++中,面向对象编程主要通过类和对象 ...
- 对比《学习R》PDF代码+《R语言实战第2版》PDF代码+《R数据科学》PDF代码分析
R语言是世界上最流行的用于数据处理和统计分析的脚本语言.考古学家用它来跟踪古代文明的传播,医药公司用它来探索哪种药物更安全.更有效,精算师用它评估金融风险以保证市场的平稳运行.总之,在大数据时代,统计 ...
最新文章
- 中信建投云计算机系列报告二,【中信建投 通信】云计算系列报告之二:电信与数通共振,光模块迎高景气(更新)...
- 全球及中国牛乳腺炎治疗系统行业发展调研及投资预测分析报告2022-2027年
- 【Python 】绘制惊艳的桑基图
- Android SharedFlow详解
- C# System.Windows.Forms.NumericUpDown 控件全选其中文字
- vscode 语法检查_Jenkins 声明式流水线的语法错误检查
- VC++实现数据包嗅探
- 【Spark】ip地址查询案例(城市热点图)
- 使用html的a标签,无法转跳到servlet页面中的解决办法,适用于servlet的初学者,不与框架相兼容
- float和int转换
- Excel VBA入门(9):实例汇总
- 公开我的开源项目newland.js
- imputation-综述文章:关于网络推理的scRNA序列插补工具基准突出了高稀疏性水平下的性能缺陷
- 电脑USB接口实现鼠标和键盘功能
- 安卓WebView的那些坑
- git 忽略某些文件
- 一款功能强大的IP查询工具!
- 深度学习那么火,深度学习图形工作站应该更火
- 使用ffmpeg视频切片并加密和视频AES-128加密后播放
- 一看就懂!renren-fast 快速开发框架使用以及开发文档