由于我是R的新手,我不知道S3方法和对象是什么.我发现有S3和S4对象系统,如果可能的话,有些人建议使用S3而不是S4(http://google-styleguide.googlecode.com/svn/trunk/google-r-style.html).但是,我不知道S3方法/对象的确切定义.
Henrik Bengtsson为互联网提供了一种在R中创建S3泛型的好方法,而不必担心它们是否在2002年之前创建过.
他的函数setGenericsS3的作用基本上是:
如果是这样,
如果没有,只需创建通用.
事实证明,当您自己的软件包中没有可用的代码时,自动创建泛型非常有用.当我们走过这个R时代时,我想知道现在在R中实现相同的正确方法是什么.我isS3Generic()
在R中找不到或类似的函数,Henrik Bengtsson的代码源自R 2.14中引入的强制命名空间.我记得我已经看到了实现同样目标的其他方法,但找不到它们.
编辑:我特意找S3.该功能isGeneric()
仅适用于S4,例如anova
(用于S3通用):
> isGeneric('anova')
[1] FALSE
> anova
function (object, ...)
UseMethod("anova")
<bytecode: 0x04dc7a18>
<environment: namespace:stats>
Run Code Online (Sandbox Code Playgroud) 我为一个使用S3类的函数创建了一个roxygen文件.我roxygenize然后建立并检查并得到一个警告:
* checking S3 generic/method consistency ... WARNING
common:
function(word.list, ...)
common.list:
function(word.list, overlap, equal.or)
See section 'Generic functions and methods' of the 'Writing R
Extensions' manual.
Run Code Online (Sandbox Code Playgroud)
所以我花时间学习:
http://cran.r-project.org/doc/manuals/R-exts.html#Generic-functions-and-methods & https://github.com/hadley/devtools/wiki/S3
但我无法弄清楚我在下面的文件中做错了什么.该功能按预期工作.
1)为什么会发出警告?2)我怎么能让它消失?
#' Find Common Words Between Groups
#'
#' Find common words between grouping variables (e.g. people).
#'
#' @param word.list A list of names chacter vectors.
#' @param overlap Minimum/exact amount of overlap.
#' @param equal.or A character vector of c(\code{"equal"}, \code{"greater"},
#' \code{"more"}, \code{"less"}).
#' @param …
Run Code Online (Sandbox Code Playgroud) 定义S3类"bar"的对象和打印方法:
foo=list(1)
class(foo) <- c("bar")
print.bar <- function(x,...){
cat("print.bar says this was ",deparse(substitute(x)),"\n")
}
Run Code Online (Sandbox Code Playgroud)
现在print(foo)执行此操作:
> print(foo)
print.bar says this was foo
Run Code Online (Sandbox Code Playgroud)
很好,但自动打印失败:
> foo
print.bar says this was structure(list(1), class = "bar")
Run Code Online (Sandbox Code Playgroud)
我猜这与线被评估为顶级表达式的方式有关.快速搜索R-devel无济于事.谁知道怎么修它?
我想要这个名字的原因是因为我定义的东西是一个函数,我希望能够在print方法中放入'try foo(2)'(从对象名称中获取'foo').是的,您可以在S3中子类化函数.我想可能还有其他的pifalls ..
我目前正在制作一个R包,并试图遵循Hadley Wickham在http://r-pkgs.had.co.nz提供的最佳实践指南.作为其中的一部分,我的目标是在DESCRIPTION文件的Imports部分中拥有所有的包依赖,而不是取决于因为我同意不会不必要地改变全球环境的理念(许多CRAN和Bioconductor包都没有似乎跟着).
我想在我的一个包函数中使用Bioconductor包rhdf5中的函数h5write()
.我现在遇到的问题是它的NAMESPACE中没有声明它的S3方法.它们是使用(例如)声明的
export(h5write.default)
export(h5writeDataset.matrix)
Run Code Online (Sandbox Code Playgroud)
而不是
S3method(h5write, default)
S3method(h5writeDataset, matrix)
Run Code Online (Sandbox Code Playgroud)
通用h5write定义为:
h5write <- function(obj, file, name, ...) {
res <- UseMethod("h5write")
invisible(res)
}
Run Code Online (Sandbox Code Playgroud)
实际上,这意味着对rhdf5 :: h5write的调用失败,因为没有注册适当的h5write方法.
据我所知,有三种解决方案:
Depends
而不是Imports
在DESCRIPTION文件中.library("rhdf5")
或require("rhdf5")
代码中的相关功能.S3methods()
而不是export()
.所有这些都有缺点.选项1表示即使从不调用我的包中的相关函数,也会加载包并将其附加到全局环境.选项2意味着library
在包中使用,同时再将包附加到全球环境中,并且根据Hadley Wickham的指南也弃用.选项3意味着依赖于另一个包作者来更新他们在Bioconductor上的包,并且还意味着不再导出S3方法,这反过来又会破坏依赖于明确调用它们的其他包.
我错过了另一种选择吗?我已经在其他地方查看了StackOverflow并发现以下有些相关的问题从另一个包导入S3方法以及
如何导出S3方法以便在命名空间中可用?但没有任何直接解决我的问题.值得注意的是,与这两者中的第一个的关键区别在于泛型和方法都在同一个包中,但问题在于使用export
而不是S3method
.
用于重现错误的示例代码(无需创建包):
loadNamespace("rhdf5")
rdhf5::h5write(1:4, "test.h5", "test")
Error in UseMethod("h5write") :
no applicable method for 'h5write' applied to an object of class
"c('integer', …
Run Code Online (Sandbox Code Playgroud) 我正在开发RSQLServer
包的一个分支,我正在尝试实现连接.使用当前版本的软件包,可以使用任何DBI连接的数据库进行连接sql_join.DBIConnection
.但是,该实现对SQL Server不起作用.例如,USING
SQL服务器不支持使用它.
我有一个这个功能的版本sql_join.SQLServerConnection
工作(虽然尚未完成).我sql_join.DBIConnection
尽可能地基于我的功能.有一个问题我已经是sql_join.DBIConnection
调用内的一些非导出的函数dplyr
,例如common_by
.现在,我通过使用来解决这个问题dplyr:::common_by
,但我知道这不是理想的做法.
我是不是该:
dplyr
?:::
运算符来调用函数?显然,使用选项3,接口可能会发生变化(因为它们不是导出函数),并且封装会在较长时间内中断.
示例代码:
sql_join.SQLServerConnection <- function (con, x, y, type = "inner", by = NULL, ...) {
join <- switch(type, left = sql("LEFT"), inner = sql("INNER"),
right = sql("RIGHT"), full = sql("FULL"), stop("Unknown join type:",
type, call. = FALSE))
by <- dplyr:::common_by(by, x, y)
using <- FALSE # all(by$x …
Run Code Online (Sandbox Code Playgroud) 所以我正在改变我在R中构建的一些函数的类,以便添加一个描述属性,因为我想使用S3泛型来为我处理所有事情.基本上,我有一个像这样的结构
foo <- function(x) x + 1
addFunction <- function(f, description) {
class(f) <- c("addFunction", "function")
attr(f, "description") <- description
f
}
foo <- addFunction(foo, "Add one")
Run Code Online (Sandbox Code Playgroud)
然后我做的事情就像
description <- function(x) UseMethod("description")
description.default <- function(x) deparse(substitute(x))
description.addFunction <- function(x) attr(x, "description")
Run Code Online (Sandbox Code Playgroud)
这很好用,但不是那么优雅.我想知道是否可以定义一个新类的函数,以便可以用类似于function
语法的语法定义此类的实例.换句话说,是能够限定addFunction
,使得foo
在下面的方式产生的:
foo <- addFunction(description = "Add one", x) {
x + 1
}
Run Code Online (Sandbox Code Playgroud)
(或者类似的东西,我对属性应该添加到函数中的位置没有强烈的感觉)?
谢谢阅读!
更新:我已经尝试了更多这个想法,但还没有真正达到任何具体结果 - 所以这只是我对当前(更新)主题的概述:
我尝试了只复制function()
-function,给它一个不同的名字,然后再操作它的想法.但是,这不起作用,我想对这里发生的事情有任何意见:
> function2 <- `function`
> identical(`function`, function2)
[1] TRUE
> function(x) …
Run Code Online (Sandbox Code Playgroud) 我想%*%
为基本矩阵子类编写一个方法。我的子类是一个 S3 类,并且 的文档help("%*%")
说它是一个 S4 泛型,并且需要为名为和%*%
的两个参数的函数编写 S4 方法。在使用之前,我已经为 S4 泛型方法编写了 S3 类的方法,并且我查看了包的源代码以获取灵感,但由于某种原因,我无法完全让它在这种情况下工作。 显示我的方法存在于我的目标签名中,但当我尝试使用它时,我的方法似乎从未真正被 R 调用。x
y
methods::setOldClass()
methods::setMethod()
{Matrix}
methods::showMethods()
x <- diag(3)
class(x) <- c("atm2d", class(matrix()))
print(x)
Run Code Online (Sandbox Code Playgroud)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
attr(,"class")
[1] "atm2d" "matrix" "array"
Run Code Online (Sandbox Code Playgroud)
默认情况%*%
下会删除我的类属性,我想保留它。
print(x %*% x)
Run Code Online (Sandbox Code Playgroud)
[,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
Run Code Online (Sandbox Code Playgroud)
我尝试%*%
为我的类创建一个方法,该方法不会删除我的类属性:
as.matrix.atm2d …
Run Code Online (Sandbox Code Playgroud) 我试图在一个包中使用S3方法,并认为我在这里问一个问题之后理解了如何设置它:使用Roxygen构建R包时的S3方法一致性警告
但现在我得到的结果我没想到.如果我直接在R中运行下面的代码,它会给我预期的结果,但是如果我把它编译成一个包,我就得不到正确的结果(请注意,当它应该只采用唯一的单词时,它会被计算两次vector a
).我不确定我的设置是不正确的.
.R文件:
#' Find Common Words Between Groups
#'
#' Find common words between grouping variables (e.g. people).
#'
#' @param word.list A list of names chacter vectors.
#' @param overlap Minimum/exact amount of overlap.
#' @param equal.or A character vector of c(\code{"equal"}, \code{"greater"},
#' \code{"more"}, \code{"less"}).
#' @param \dots In liu of word.list the user may input n number of character
#' vectors.
#' @rdname common
#' @return Returns a dataframe of all words …
Run Code Online (Sandbox Code Playgroud) 我想为数组定义一个不同的打印方法,但我担心我不了解S3调度.如果我明确地调用print(x),则会调用我的自定义打印方法,但如果我只是在控制台上键入x,则不会调用它.但是,如果我定义自定义S3类,则调用适当的print方法.
如果我尝试为print.numeric定义一个方法,会发生类似的事情
这是一个最小的例子:
print.array <- function(x, ...) cat("Hi!\n")
x <- array(1:8, c(2,2,2) )
print(x) # the print method defined above is called
# Hi!
x # the print method defined above is NOT called
Run Code Online (Sandbox Code Playgroud)
有没有人对正在发生的事情有任何见解?x
在控制台上进行评估时,实际进行打印的功能是什么?