使用该class
函数可以让我们确定一个对象的类:
> x = 5
> class(x)
[1] "numeric"
Run Code Online (Sandbox Code Playgroud)
我也明白我们可以使用is.object
命令来确定一个对象是否有一个类。然而,一些对象类型是隐式的,即
> is.object(x)
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
声明 R 中的所有变量都是对象并且is.object
仅是对非隐式类的测试是否正确?
另外,类型如何适应这个。天真地,我认为以下代码会产生错误:
> x = 5
> class(x) = "fake"
> x = X + 1
> x + 1
[1] 6
attr(,"class")
[1] "fake"
Run Code Online (Sandbox Code Playgroud)
但x
仍然有“double”类型,一切仍然有效。可以将类型视为所有其他对象都继承自的超类吗?
请考虑以下代码:
> A <- matrix(1:12, ncol=4)
> colnames(A) <- letters[1:4]
> class(A) <- c("foo", "matrix")
Run Code Online (Sandbox Code Playgroud)
当A是子集时,它会丢失"foo"类标签:
> class(A[1:2,])
[1] "matrix"
Run Code Online (Sandbox Code Playgroud)
矢量也是如此.然而,data.frames不会发生同样的情况:
> B <- as.data.frame(A)
class(B) <- c("foo", "data.frame")
> class(B[1:2,])
[1] "foo" "data.frame"
Run Code Online (Sandbox Code Playgroud)
通常,将泛型函数应用于对象会保留class属性.不适用于矩阵/数字/整数对象.为什么?并且可以避免这种行为吗?
我想查看与某个对象类关联的所有方法的列表.例如,如果我看到一些模型拟合例程返回类"富"的目标,我想知道,如果包(或任何其它封装)定义方法,如simulate.foo
,update.foo
,coef.foo
,print.foo
等我该怎么办呢?
我知道这methods
解决了逆问题(假设有一个S3类),但显然我不想搜索已定义print
函数的每个对象,以便找出我感兴趣的类是否有一个.我可能在这里忘记了一些非常简单的事情.谢谢!
(理想情况下,看到S3和S4类的解决方案会很好).
更新:理想情况下,解决方案应该显示隐藏的方法,就像methods
函数一样.例如,methods("simulate")
显示:
> methods("simulate")
[1] simulate.lm*
Run Code Online (Sandbox Code Playgroud)
因此,在查询与lm
该类关联的方法时,我们希望恢复此模拟方法.
我试图了解 R 中的 s3 类系统。
文档说我需要为我想要创建的方法创建一个通用函数。
假设我想foo
为 class创建一个方法XYZ
。
有了 R 的所有包,我怎么能确定我没有覆盖以前创建的泛型方法?
总结是一个不好的例子,因为每个人都可能知道它已经存在,但是我的泛型可能已经定义在我已经加载或我将加载的包中。
我定义了两个类,它们可以成功添加两个自己的对象或一个数字和一个自己的对象。
a <- structure(list(val = 1), class = 'customClass1')
b <- structure(list(val = 1), class = 'customClass2')
`+.customClass1` <- function(e1, e2, ...){
val1 <- ifelse(is.numeric(e1), e1, e1$val)
val2 <- ifelse(is.numeric(e2), e2, e2$val)
val_res <- val1 + val2
print('customClass1')
return(structure(list(val = val_res), class = 'customClass1'))
}
`+.customClass2` <- function(e1, e2, ...){
val1 <- ifelse(is.numeric(e1), e1, e1$val)
val2 <- ifelse(is.numeric(e2), e2, e2$val)
val_res <- val1 + val2
print('customClass2')
return(structure(list(val = val_res), class = 'customClass1'))
}
print.customClass1 <- function(x, ...){
print(x$val)
}
print.customClass2 …
Run Code Online (Sandbox Code Playgroud) 我已经阅读了以下两个讨论:
Roxygen2 - 如何在
使用 Roxygen 构建 R 包时正确记录 S3 方法S3 方法一致性警告
以及以下两个教程:
http : //cran.r-project.org/doc/manuals/R-exts .html#Generic-functions-and-methods
http://adv-r.had.co.nz/S3.html,
但我的问题仍然没有解决。以下是详细信息:
我想在一个包中定义一个 S3 的 plot() 泛型方法,我的代码是:
#' description
#'
#' more details
#'
#' @param x "test" object
#' @param label parameter one
#' @param log parameter two
#' @param ... graphical parameters to plot
#'
#' @examples
#' plot(a)
#'
#' @export
plot <- function(x, label=TRUE, log=TRUE, ...){
UseMethod("plot")
}
#' @export
plot.test <- function(x, label=TRUE, log=TRUE, ...){ …
Run Code Online (Sandbox Code Playgroud) 我正在尝试将S3"Math"组泛型用于自定义类.但是我得到了一个奇怪的结果:log()
同时工作log2
并log10
产生错误.以下是一个最小的例子:
# simple class with just the new name
lameclass <- function(x) {
class(x) <- append(class(x), "lame")
x
}
# It prints something when Math generics methods are used
Math.lame <- function(x, ...) {
print("I am lame")
NextMethod()
}
# an object of the class
lamevector <- lameclass(1:10)
> class(lamevector)
[1] "integer" "lame"
Run Code Online (Sandbox Code Playgroud)
现在试着打电话log
:
log(lamevector)
[1] "I am lame"
[1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101 2.0794415 2.1972246 2.3025851
Run Code Online (Sandbox Code Playgroud)
基数为2:
log(lamevector, …
Run Code Online (Sandbox Code Playgroud) 我有一个 R 包(目前不在 CRAN 上),它定义了来自其他包(特别是knitr::knit_print
和huxtable::as_huxtable
)的几个通用函数的 S3 方法。但是,它们不是我的包的关键部分,所以我不想在用户安装我的包时创建对这些包的依赖。在 R 4.0.0 之前,我导出了 S3 方法而不导入泛型。使用roxygen2
,我的@export
指令被翻译成export()
NAMESPACE 中的指令而不是S3method()
. 这在 R 版本 < 4.0.0 中运行良好,因为 R 首先在全局环境中查找匹配generic_function.class
方法,而不是依赖于 S3 方法的正确注册。但是,根据developer.r-project.org 上的这篇博客,R 不再查找未注册的 S3 方法。
最好的方法是什么?现在,我已经@importFrom
在roxygen2
块中添加了指令,并将两个包都添加到了说明的导入部分。但是,据我所知,这意味着安装我的软件包的任何用户都必须安装knitr
,huxtable
无论他们是否愿意。
我想创建一个 S3 类。我如何确定哪种设置 class 属性的方法是正确的(因为它会有所不同)?
1) 覆盖类属性
object <- data.frame(field1 = "a", field2 = 2)
class(object)
# [1] "data.frame"
class(object) <- "MyClass" # set the class by overwriting the existing one
class(object)
# [1] "MyClass"
Run Code Online (Sandbox Code Playgroud)
2) 附加类属性
我还可以附加类名(在开头或结尾):
object2 <- data.frame(field1 = "a", field2 = 2)
class(object2) <- append(class(object2), "MyClass")
class(object2)
# [1] "data.frame" "MyClass"
object3 <- data.frame(field1 = "a", field2 = 2)
class(object3) <- append("MyClass", class(object3))
class(object3)
# [1] "MyClass" "data.frame"
Run Code Online (Sandbox Code Playgroud)
我知道在开头和结尾附加类名可能会改变被调用的函数(来自?class
):
当通用函数 fun 应用于具有类属性 c("first", "second") …
我正在尝试扩展data.table
以加速/标准化复杂调查设计的分析。为此,我试图[.data.table
在我拦截调用的位置上添加一个轻层,j
并在某些情况下在需要特殊调查类型命令时替换操作(例如mean
to median
)(或在特殊情况下使用正常功能不需要利用data.table
的 geforce 类型优化)。
基于我对 s3 调度的部分理解,NextMethod
这里应该是合适的函数,但它似乎j
作为符号传递j
(例如,a[, j]
而不是a[, median(v1)]
它与 data.table 的 NSE 奇怪地交互。我已经尝试过使用 do.call 的版本,但不能不要通过一些无限递归的废话(do.call('[', ...)
将无休止地发送[.dtsurvey
)
有没有一种干净的方法来调整参数并将其传递给data.table
?在下面的例子玩具,我想有调用返回median
列的v1
,即使初始操作mean
。
library('data.table')
a = data.table(v1 = 1:10)
b = copy(a)
"[.dtsurvey" <- function(x, i, j, by, ...){
j = substitute(j)
print(j)
if(j[[1]] == 'mean') j[[1]] = quote(median)
print(j)
NextMethod(`[`, …
Run Code Online (Sandbox Code Playgroud)