gpt4 book ai didi

r - `UseMethod()` vs `继承(R中的)` to determine an object'的类

转载 作者:行者123 更新时间:2023-12-02 06:46:18 26 4
gpt4 key购买 nike

如果需要根据R对象的类以不同的方式处理R对象,则可以在单个函数中使用ifelse:

foo <- function (x) {
if (inherits(x, 'list')) {
# Foo the list
} else if (inherits(x, 'numeric')) {
# Foo the numeric
} else {
# Throw an error
}
}

或者我可以定义一个方法:
foo <- function (x) UseMethod('foo')

foo.list <- function (x) {
# Foo the list
}
foo.numeric <- function (x) {
# Foo the numeric
}

每种方法的优点是什么?有性能影响吗?

最佳答案

好的,有一些背景可以回答这个问题(我认为)...

在R中,在具有用户定义的对象结构或对象(例如因子 vector 或数据框)的情况下,对象的类是显式的,其中其他属性在对象本身的处理中(例如,级别)起着重要作用因子 vector 的标签或数据框中的变量名是可修改的属性,在访问每个对象的观察结果时起主要作用。

但是请注意,基本的R对象(例如 vector ,矩阵和数组)是隐式分类的,这意味着该类未使用属性函数进行标识。无论是隐式还是显式,始终可以使用特定于属性的函数类来检索给定对象的类。

当将通用函数foo应用于具有类属性c(“first”,“second”)的object时,系统搜索名为foo.first的函数,如果找到该函数,则将其应用于对象。如果找不到这样的函数,则尝试一个名为foo.second的函数。如果没有任何类名会产生合适的函数,则使用函数foo.default(如果存在)。如果没有类属性,则尝试使用隐式类,然后使用default方法。

函数类输出对象继承的类的名称的 vector 。
class <-设置对象继承的类。

Inherits()指示其第一个参数是否继承自中指定的任何参数。方法分派(dispatch)基于泛型函数的第一个参数的类进行。如果为TRUE,则返回与返回长度相同的整数 vector 。每个元素指示在类别(x)中与what元素匹配的位置;零表示没有匹配项。如果哪个为FALSE,则如果任何名称与任何类匹配,则继承会返回TRUE。

除了Inherits()之外,所有都是原始函数。

注意事项

好的,现在让我们以相反的顺序考虑您的示例...

foo <- function (x) UseMethod('foo')

foo.list <- function (x) {
# Foo the list
}
foo.numeric <- function (x) {
# Foo the numeric
}


现在,如果我们使用函数methods()
methods(foo)
[1] foo.list foo.numeric
see '?methods' for accessing help and source code
> getS3method('foo','list')
function (x) {
# Foo the list
}

因此,我们有一个 foo类和两个关联的方法 foo.listfoo.numeric。因此,我们现在知道 foo类具有支持 listnumeric操作的方法。

好的,现在让我们考虑您的第一个示例...
function (x) {
if (inherits(x, 'list')) {
# Foo the list
print(paste0("List: ", x))
} else if (inherits(x, 'numeric')) {
# Foo the numeric
print(paste0("Numeric: ", x))
} else {
# Throw an error
print(paste0("Unhandled - Sorry!"))
}
}


问题是这不是s3类,而是R函数。如果对 methods()运行 foo,它将返回“找不到方法”
> methods(foo)
no methods found
> getS3method('foo','list')
Error in getS3method("foo", "list") : no function 'foo' could be found

那么第二个例子中发生了什么? Inherits()操作与参数的类匹配。 Inherits()->方法分配是基于泛型函数的第一个参数的类进行的。

因此,您的第一个示例只是查找 函数参数x 的类,因此不会创建或存在任何S3类。

每种方法的优点是什么?有性能影响吗?

好的,我这里有些偏见,但是对象的类是描述R中实体的最有用的属性之一。您创建的每个对象都至少由一个类隐式或显式地标识。 R是一种面向对象的编程语言,意味着实体存储为对象并具有作用于它们的方法。

所以第二种方法是我认为的方法。为什么?因为您确实在按预期使用语言构造。显式使用Inherits()的第一种方法感觉很像黑客。从我个人的角度来看,可读性是理解的关键,因此我担心阅读第一个示例的人可能会被问到一个问题:“他们(程序员)为什么采用这种方法,我想念的是什么?”。然后,我担心的是要避免复杂性,因为它会妨碍代码理解。因此,保持简单有利于代码理解。

关于代码性能,if-else解析器通常比对象查找模型快,尽管查找模型并不等同于类映射过程,所以我认为在这种情况下很难回答性能问题。为什么?两种方法是不同的。

希望以上内容为您指明正确的方向。保持安全,良好的因果关系将如您所愿。

这里有几本书的建议:
  • R Inferno by Patrick Burns
  • Advanced R by Hadley Wickham
  • 面向所有人的
  • R:高级分析和图形
  • 关于r - `UseMethod()` vs `继承(R中的)` to determine an object'的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61322898/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com