济南网站建设与维护,网络建设方案模板,仓库管理系统app,百度快照不更新怎么办本文对应《R语言编程艺术》 第7章#xff1a;R语言编程结构#xff1b; 第9章#xff1a;面向对象的编程#xff1b; 第13章#xff1a;调试 R语言编程结构 控制语句#xff1a; 循环#xff1a; for (n in x) { }
while (condition) { }
repeat { }另外break也可以用在…本文对应《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语句里的控制条件里出现向量并且长度大于1R的处理方式是将向量的第一个元素作为控制条件返回结果然后提示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) - vR语言会尝试用以下方式执行 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类 #定义类employeesetClass(“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 #引用成员变量joesalary[1] 55000 slot(joe, “salary”)[1] 55000 #赋值也可以使用这两种方法joesalary - 88000slot(joe, “salary”) - 88000S4类的安全性在于如果给不存在的成员变量赋值会有报错消息而S3类将会新建一个成员变量。 joesalry - 48000Error in checkSlotAssignment(object, name, value) :“salry” is not a slot in class “employee”在S4类上实现泛型函数 #show()函数指在交互模式下输入变量名直接打印
setMethod(“show”, “employee”,
function(object) {inorout - ifelse(objectunion, “is”, “is not”)cat(objectname, “has a salary of”, objectsalary,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