“S3方法”在R中意味着什么?

时间:2011-07-05 12:13:30

标签: r r-faq r-s3

由于我对R很新,我不知道S3方法和对象是什么。我发现有S3和S4对象系统,如果可能的话,有些人建议使用S3而不是S4(http://google-styleguide.googlecode.com/svn/trunk/google-r-style.html)。但是,我不知道S3方法/对象的确切定义。

6 个答案:

答案 0 :(得分:76)

查看?S3?UseMethod可以找到大部分相关信息,但简而言之:

S3指的是方法调度方案。如果您已经使用了R一段时间,您会发现有很多不同类型的对象有printpredictsummary方法。

在S3中,这适用于:

  • 设置对象的类 兴趣(例如:a的回报值) 对方法glm的调用具有类glm
  • 提供一般的方法 名称(例如print),然后是一个点,和 然后是类名(例如: print.glm
  • 必须做一些准备 完成此通用名称(print) 为了这个工作,但如果你是 只是想让自己顺从 现有的方法名称,您不需要 这(请参阅我提到的帮助 如果你这样做,那就更早了。)

对于旁观者,尤其是新创建的时髦模型拟合包的用户而言,能够键入predict(myfit, type="class")predict.mykindoffit(myfit, type="class")更方便。

还有更多内容,但这应该让你开始。这种基于对象的属性(类)调度方法的方式存在很多缺点(而且纯粹主义者可能会在晚上醒来时很恐怖),但在很多情况下,它的工作正常。使用当前版本的R,已经实现了更新的方法(S4和参考类),但大多数人仍然(仅)使用S3。

答案 1 :(得分:46)

要开始使用S3,请查看median函数的代码。在命令提示符下键入median表明它的主体中有一行,即

UseMethod("median")

这意味着它是一种S3方法。换句话说,您可以为不同的S3类使用不同的median函数。要列出所有可能的中位数方法,请键入

methods(median) #actually not that interesting.  

在这种情况下,只有一种方法,即默认方法,可以调用任何方法。您可以通过键入

来查看该代码
median.default

一个更有趣的例子是print函数,它有许多不同的方法。

methods(print)  #very exciting

请注意,某些方法的名称旁边有*个。这意味着它们隐藏在某个包的命名空间中。使用find找出他们所在的包。例如

find("acf")  #it's in the stats package
stats:::print.acf

答案 2 :(得分:33)

来自http://adv-r.had.co.nz/OO-essentials.html

  

R的三个OO系统在定义类和方法方面有所不同:

     
      
  • S3实现了一种称为泛型函数OO的OO编程风格。   这与大多数编程语言不同,如Java,C ++和   C#,实现消息传递OO。通过消息传递,消息   (方法)被发送到对象,对象确定哪个函数   打电话。通常,此对象在方法中具有特殊外观   呼叫,通常出现在方法/消息的名称之前:例如   canvas.drawRect("蓝色&#34)。 S3是不同的。虽然计算仍在进行中   通过方法执行,一种称为泛型的特殊类型的函数   函数决定调用哪个方法,例如drawRect(canvas," blue")。   S3是一个非常随意的系统。它没有正式的类定义。

  •   
  • S4的工作方式与S3相似,但更为正式。主要有两个   与S3的差异。 S4有正式的类定义,用来描述   每个类的表示和继承,并有特殊的帮助   用于定义泛型和方法的函数。 S4也有多个   dispatch,这意味着泛型函数可以选择基于的方法   任意数量的参数的类,而不仅仅是一个。

  •   
  • 简称为RC的引用类与S3完全不同   和S4。 RC实现消息传递OO,因此方法属于   课程,而不是功能。 $用于分隔对象和方法,所以   方法调用看起来像canvas $ drawRect(" blue")。 RC对象也是   可变:他们不使用R的通常的复制修改语义,但是   修改到位。这使他们更难以推理,但允许   它们用于解决S3或S4难以解决的问题。

  •   
     

另外还有一个系统不是OO,但它很重要   在这里提一下:

     
      
  • 基类型,构成另一个OO的内部C级类型   系统。基本类型主要使用C代码进行操作,但它们是   重要的是要知道因为它们提供了构建块   其他OO系统。
  •   

答案 3 :(得分:11)

我来到这个问题,主要是想知道名字的来源。从this wikipedia article看来,该名称是指R所基于的S编程语言的版本。其他答案中描述的方法调度方案来自S,并根据版本进行适当标记。

答案 4 :(得分:7)

尝试

methods(residuals)

其中列出了“residuals.lm”和“residuals.glm”。这意味着当您拟合线性模型m和类型residuals(m)时,将调用residuals.lm。当您拟合广义线性模型时,将调用residuals.glm。 这种C ++对象模型是颠倒的。在C ++中,您定义了一个具有虚函数的基类,这些函数被派生的类重写。 在R中,您定义了一个虚拟(也称为通用)函数,然后您决定哪些类将覆盖此函数(也称为定义方法)。请注意,执行此操作的类不需要从一个公共超类派生。 我不同意通常更喜欢S3而不是S4。 S4有更多的形式(=更多的打字),这对某些应用来说可能太多了。但是,S4类可以像C ++中的类或结构一样定义。您可以指定某个类的对象由字符串和两个数字组成,例如:

setClass("myClass", representation(label = "character", x = "numeric", y = "numeric"))

使用该类的对象调用的方法可以依赖具有这些成员的对象。这与S3类非常不同,后者只是一堆元素的列表。

使用S3和S4,您可以按fun(object, args)而非object$fun(args)调用成员函数。如果您正在寻找类似后者的东西,请查看原型包。

答案 5 :(得分:0)

这里是根据Hadley Wickham(首席科学家)的“ Advanced R,第二版” (CRC出版社,2019年)更新的众多 R对象系统的快速精简版本。 (在RStudio中),基于关于here的章节,其网络表示为Object-Oriented Programming

Advanced R book cover

2015年的第一版具有网络表示形式here,并在OO here上有相应的章节。

面向对象系统的方法

Hadley定义以下内容来区分两种不同的面向对象编程方法:

功能性OOP :方法(可调用的代码段)属于 generic functions (不要与Java / C#generic methods混淆)。可以将这些方法视为位于全局查找表中。运行时系统根据函数的名称以及传递给该函数的一个或多个参数的类型(或对象类)来找到要执行的方法(称为“方法分派”)。就语法而言,方法调用可能看起来像普通的函数调用:myfunc(object, arg1, arg2)。此调用将导致运行时查找与(“ myfunc”,typeof(object))对关联的方法,或者可能与(“ myfunc”,typeof(object),typeof(arg1)相关联的方法。 ),typeof(arg2))(如果语言支持)。在R的S3中,泛型函数的全名给出(函数名,类)对。例如:mean.Date是计算日期均值的方法。尝试使用methods("mean")列出功能名称为mean的通用方法。例如,在OO先锋SmalltalkCommon Lisp Object SystemJulia中可以找到功能性OOP方法。 Hadley指出“与R相比,Julia的实现是完全开发的,并且性能极佳。”

封装的OOP :方法属于对象或类,并且方法调用通常看起来像object.method(arg1, arg2)。之所以称为 encapsulated ,是因为对象同时封装了 data (字段)和 behaviour (方法)。可以将该方法视为位于对象或对象的类说明所附的查找表中。运行时会根据方法名称以及一个或多个参数的类型来查找方法。这是在“流行”的OO语言(例如C ++,Java,C#)中发现的方法。

在两种情况下,如果都支持继承(可能是继承),则运行时可以向上遍历类层次结构,直到找到与调用查找键匹配的对象为止。

如何找出R对象所属的系统

library(sloop) # formerly, "pryr"
otype(mtcars)
#> [1] "S3"

R对象系统

S3

  • 功能性面向对象的方法。
  • 根据哈德利所说的最重要的系统。
  • 最简单,最常见。 R使用的第一个OO系统。
  • 带有基本R,在整个基本R中使用。
  • 依靠惯例而不是强制保证。
  • 请参见 Chambers,John M和Trevor J Hastie。 1992年。“ S中的统计模型”。 Wadsworth&Brooks /科尔高级图书与软件。
  • “ Advanced R,第二版” here中的详细信息。

S4

  • 功能性面向对象的方法。
  • 根据哈德利(Hadley)排名第三的最重要系统。
  • S3的重写,因此与S3类似,但更正式,更严格:它迫使您仔细考虑程序设计。适用于构建大型系统(例如Bioconductor项目)。
  • 在基本的“方法”包中实现。
  • 请参阅: Chambers,John M.,1998年。“使用数据编程:S语言指南”。施普林格。
  • “ Advanced R,第二版” here中的详细信息。

RC又称为“参考课程”

  • 封装的OOP方法。
  • 带有基数R。
  • 基于S4。
  • RC对象是S4对象的特殊类型,它们也是“可变的”。即可以使用就地修改而不是使用R的通常的修改时复制语义。请注意,可变状态是hard to reason about,并且是丑陋错误的来源,但在某些应用程序中可能导致更有效的代码。

R6

  • 封装的OOP方法。
  • Hadley认为第二重要的系统。
  • 可以在 R6 程序包(与library(R6)一起安装)中找到
  • 与RC类似,但更轻便,速度更快:它不依赖于S4或 methods 包。建立在R环境之上。也有:
    • 公共和私有方法
    • 活动绑定(访问时实际上调用方法的字段)
    • 可在包中使用的类继承
    • 类方法(属于类并且可以通过selfprivatesuper访问实例的代码)和成员函数< / em>(分配给字段的函数,但不是方法,而只是函数)
  • 提供了一种逃避R的“修改时复制”语义的标准化方法
  • 请参阅打包站点:"R6: Encapsulated object-oriented programming for R"
  • “ Advanced R,第二版” here中的详细信息。

其他

还有其他名称,例如 R.oo (类似于RC), proto (基于原型,使用JavaScript)和 Mutatr 。但是,“高级R”表示:

  

除了被广泛使用的R6,这些系统主要是   理论兴趣。他们确实有长处,但R用户很少   了解并理解它们,因此他人难以阅读和理解   为您的代码做出贡献。

也请务必阅读“ Advanced R,第二版” 中的trade-offs章节。