随笔分类 - R
摘要:在前面的小节中,我们掌握了如何运用 R 中已有的类和方法处理模型对象。在 S3 系统中,允许自行创建类和泛型函数。前面的例子中,我们使用条件表达式模拟了 head( )的方法分派。虽然模拟成功了,但一般不建议这样做。S3 泛型函数非常灵活,而且很容易拓展。在定义泛型函数时,我们通常创建一个函数去调用
阅读全文
摘要:S3 泛型函数和方法在统一各种模型的使用方式上是最有用的。例如,我们可以创建一个线性模型,使用泛型函数从不同角度查看模型信息:lm1 <- lm(mpg ~ cyl + vs, data = mtcars)在前面的章节中,我们提到过线性模型本质上是由模型拟合产生的数据字段构成的列表。这就是为什么 l
阅读全文
摘要:正如本章前面提到的,一个类可以用多种方法定义它的行为,尤其是它与其他类的关系。在 S3 系统中,我们可以创建泛型函数(generic function),对于不同的类,由泛型函数决定调用哪个方法,这就是 S3 方法分派(method dispatch)的工作机理。对象的类不同,其方法分派也不同。因此
阅读全文
摘要:继承是面向对象编程的另一个重要概念。所谓继承,就是指一个类继承了另一个基础(或高级)类的行为,并且还有一些新的特征。通常来说,基础类是一个更抽象更宽泛的概念,继承类则比较具体和明确。这些都可以从日常生活中得到证实。举个例子,dog 和 cat 是两个类,并且从 animal 类中继承而来。anima
阅读全文
摘要:如果你是来自 Java、Python、C++、C# 等编程语言的开发人员,那么,应该熟悉面向对象的编码风格。但是,如果不熟悉任何其他面向对象的编程语言,就可能会对这个术语感到困惑,因为它听起来有点抽象。但是,不必担心,我们从编程的核心出发,就会发现 它其实很容易理解。当我们谈到编程时,实际上是在讲如
阅读全文
摘要:本章最重要的概念就是类和方法。类描述对象是什么?方法定义对象可以做什么?对于这些概念,现实世界中的示例不计其数。例如,animal 是一个类,在这个类中,我们可以定义诸如发声和移动等方法。vehicle 也是一个类,在这个类中,我们可以定义诸如启动、移动和停止等方法。类似地,person 也是一个类
阅读全文
摘要:上一章,我们掌握了环境的结构和性质,以及如何创建并访问环境。环境在惰性求值、复制—修改和词法作用域中起到了非常关键的作用,在创建和调用函数时,相关的环境会自动启用这些机制。对函数的运行方式有了扎实的理解之后,就可以学习函数更高级的用法。本章将要学习使 R 在交互式分析中更灵活的元编程(Metapro
阅读全文
摘要:上一节介绍了 R 中的函数式编程工具,理解了函数只是另一种可以被传递的对象。当创建一个新函数 fun( ) 时,也同时创建了一个与函数相关联的环境。这个环境被称作函数的封闭环境,可以通过 environment(fun) 访问。每次调用该函数时,一个新的包含尚未求值的实参(也称为 promise )
阅读全文
摘要:在前面几节中,我们学习了如何使用 quote( ) 和 substitute( ) 将表达式捕获为语言对象,以及如何使用 eval( ) 在给定列表或环境中计算表达式。这些函数组成了 R 中元编程的基本功能,这使我们能够调整标准计算。元编程的主要应用是执行非标准计算以使某些特定用法更容易。接下来的内
阅读全文
摘要:捕获表达式之后,下一步就是对其进行求值,可以用 eval( ) 函数完成这个工作。例如,如果在控制台键入 sin(1) 并且按下回车键,会立即显示出结果:sin(1)## [1] 0.841471为了控制 sin(1) 的计算过程,我们可以使用 quote( ) 捕获此表达式,然后调用eval( )
阅读全文
摘要:当我们在控制台输入一个表达式并按下回车键时, R 会执行表达式并显示输出结果。如下例所示: rnorm(5)## [1] 0.54744813 1.15202065 0.74930997 -0.02514251## [5] 0.99714852这里生成了 5 个随机数。subset( ) 神奇的地方
阅读全文
摘要:上一章,我们系统地学习了函数的工作方式,包括参数何时被计算(惰性求值),修改参数会发生什么(复制—修改),以及在何处查找未在函数内部定义的变量(词法作用域)。这些术语看起来好像有些难度,但其实并不难。在接下来的内容中,我们将学习两种函数:一种是在函数内部定义的函数,另一种是与其他函数组合使用的函数。
阅读全文
摘要:上一节讨论了闭包,即定义在父函数中的函数。接下来要讨论的是高阶函数,也就是将另一个函数作为参数的函数。在进入这个专题之前,我们需要先了解一下,当一个函数作为变量或参数传递给另一个函数时的具体运行方式。1.为函数创建别名首先要考虑的问题是:如果将一个现有的函数赋给一个变量,会影响函数的封闭环境吗?如果
阅读全文
摘要:函数内部定义的函数称为闭包(closure)。闭包的特点是在其函数体中,可以使用局部参数,也可以使用其父环境中的变量。举个例子,假设我们有如下函数:add <- function(x, y) {x + y}此函数有两个参数。每次调用 add( ) 函数时,都需要提供这两个参数。如果使用闭包,就可以生
阅读全文
摘要:在前面的章节中,我们已经学习了 R 语言的基础功能,并且了解了如何运用向量、矩阵、列表和数据框表示不同形式的数据,以及用内置函数解决简单的问题。但是仅仅了解这些功能并不能解决所有问题。现实中的数据分析通常需要对数据进行仔细的转换和聚合,而这些操作则需要各种各样内置的或是由扩展包提供的函数。为了避免对
阅读全文
摘要:我们学习了惰性求值、复制—修改机制和词法作用域。这些机制与一种对象高度相关,那就是环境。事实上,词法作用域完全依赖于环境。尽管环境看起来与列表很相似,在某些方面它们其实是完全不同的两个概念。下面几节我们会通过创建和操作环境对象来了解它的行为,以及查看它的结构如何决定 R 函数的运行。 环境对象 创建
阅读全文
摘要:不仅是全局环境,函数环境也会控制符号的查找。有 3 个与函数及其运行过程相关的重要环境:执行环境(executing environment)、封闭环境(enclosing environment)和调用环境(calling environment)。每次调用函数时,R 都会创建一个新的环境来主管函
阅读全文
摘要:环境有父环境,如果一个符号不存在于环境中,R 就会到它的父环境中查找。假设我们对环境中的一个变量使用 get( ) 函数。如果在此环境中找到该变量,则获取其值,否则函数将会在父环境中查找该变量。和前面创建环境 e1 一样,我们再创建一个新的环境 e2,令 e1 为 e2 的父环境:e2 <- new
阅读全文
摘要:我们使用 new.env( ) 函数创建一个新环境:e1 <- new.env()环境通常用十六进制数表示,即内存地址:e1## <environment: 0x0000000014a45748>我们可以用提取操作符($ 和 [[)在环境中创建变量,其代码形式类似于修改一个列表:e1$x <- 1e
阅读全文
摘要:环境是由一组名称组成的对象,每个环境(除了空环境)都有一个父环境。每个名称(也称为符号或变量)都指向一个对象。当我们查找一个符号时,如果它在当前环境中,R 就会在当前环境中搜索并返回该符号指向的对象。如果这个符号在当前环境中没有找到,R 就会到它的父环境中搜索(直到找遍所有环境)。图 8-1 说明了
阅读全文