虽然我的问题与最近的问题有关,但我怀疑它的答案与R S4对象系统的详细工作方式有关.
(TLDR; - 所有指示都as(4L, "numeric")应该发送到一个函数,它的身体as.numeric(4L)用来将它转换为一个"numeric"向量.)
每当as(object, Class)用户将对象转换为所需对象时Class,就会触发对幕后调用coerce().coerce()反过来,有一堆方法根据函数调用的签名调度 - 这里是第一个和第二个参数的类.要查看所有可用S4 coerce()方法的列表,可以运行showMethods("coerce").
这样做表明只有一种方法可以转换为类"numeric".这是签名的from="ANY", to="numeric":
showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
# ... snip ...
# from="ANY", to="numeric"
# ... snip ...
Run Code Online (Sandbox Code Playgroud)
该方法用于as.numeric()执行其转换:
getMethod("coerce", c("ANY", "numeric"))
# Method Definition:
#
# function (from, to, strict = TRUE)
# {
# value <- as.numeric(from)
# if (strict)
# attributes(value) <- NULL
# value
# }
# <environment: namespace:methods>
#
# Signatures:
# from to
# target "ANY" "numeric"
# defined "ANY" "numeric"
Run Code Online (Sandbox Code Playgroud)
鉴于它的签名,以及它是coerce()转换为类的唯一方法这一事实"numeric",我希望上面显示的函数是通过调用调度的函数as(4L, "numeric").只有通过运行以下两项检查才能加强这种期望.
## (1) There isn't (apparently!) any specific method for "integer"-->"numeric"
## conversion
getMethod("coerce", c("integer", "numeric"))
# Error in getMethod("coerce", c("integer", "numeric")) :
# no method found for function 'coerce' and signature integer, numeric
## (2) This says that the "ANY"-->"numeric" method will be used for "integer"-->"numeric"
## conversion
selectMethod("coerce", signature=c("integer", "numeric"))
# Method Definition:
#
# function (from, to, strict = TRUE)
# {
# value <- as.numeric(from)
# if (strict)
# attributes(value) <- NULL
# value
# }
# <environment: namespace:methods>
#
# Signatures:
# from to
# target "integer" "numeric"
# defined "ANY" "numeric"
Run Code Online (Sandbox Code Playgroud)
(TLDR;实际上,调用as(4L, "numeric")load和dispatches到一个什么都不做的方法.)
尽管上面提到的所有迹象,as(4L, "numeric")都不会调度coerce()带签名的调用方法c("ANY", "numeric").
以下是一些显示方式:
## (1) as.numeric() would do the job, but as(..., "numeric") does not
class(as(4L, "numeric"))
#[1] "integer"
class(as.numeric(4L))
# [1] "numeric"
## (2) Tracing shows that the "generic" method isn't called
trace("coerce", signature=c("ANY", "numeric"))
as(c(FALSE, TRUE), "numeric") ## <-- It's called for "logical" vectors
# Tracing asMethod(object) on entry
# [1] 0 1
as(c("1", "2"), "numeric") ## <-- and for "character" vectors
# Tracing asMethod(object) on entry
# [1] 1 2
as(c(1L, 2L), "numeric") ## <-- but not for "integer" vectors
# [1] 1 2
untrace("coerce")
Run Code Online (Sandbox Code Playgroud)
什么方法,那么,被使用?好吧,显然调用的行为在as(4L, "numeric")
方法列表中添加了一个新的S4方法coerce(),并且它是使用的方法.
(比较下面的调用的结果会产生什么之前,我们曾试图我们第一次"integer"来"character"转换.)
## At least one conversion needs to be attempted before the
## "integer"-->"numeric" method appears.
as(4L, "numeric")
## (1) Now the methods table shows a new "integer"-->"numeric" specific method
showMethods("coerce")
# Function: coerce (package methods)
# from="ANY", to="array"
# ... snip ...
# from="ANY", to="numeric"
# ... snip ...
# from="integer", to="numeric" ## <-- Here's the new method
# ... snip ...
## (2) selectMethod now tells a different story
selectMethod("coerce", signature=c("integer", "numeric"))
# Method Definition:
#
# function (from, to = "numeric", strict = TRUE)
# if (strict) {
# class(from) <- "numeric"
# from
# } else from
# <environment: namespace:methods>
#
# Signatures:
# from to
# target "integer" "numeric"
# defined "integer" "numeric"
Run Code Online (Sandbox Code Playgroud)
为什么不as(4L, "numeric")派遣到可用的coerce()方法signature=c("ANY", "numeric")?
如何/为什么它会在S4方法表中添加新方法?
从哪里(在R的源代码或其他地方)确定coerce()方法的定义signature=c("integer", "numeric")?
小智 0
查看 的源代码as(),它分为两部分。(为了清晰起见,源代码已被缩短)。首先,它会查找 的现有方法coerce(),如上所述。
function (object, Class, strict = TRUE, ext = possibleExtends(thisClass,
Class))
{
thisClass <- .class1(object)
where <- .classEnv(thisClass, mustFind = FALSE)
coerceFun <- getGeneric("coerce", where = where)
coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun),
inherited = TRUE)
asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun,
coerceMethods, where)
# No matching signatures from the coerce table!!!
if (is.null(asMethod)) {
sig <- c(from = thisClass, to = Class)
asMethod <- selectMethod("coerce", sig, optional = TRUE,
useInherited = FALSE, fdef = coerceFun, mlist = getMethodsForDispatch(coerceFun))
Run Code Online (Sandbox Code Playgroud)
如果没有找到任何方法(如本例所示),它将尝试创建一个新方法,如下所示:
if (is.null(asMethod)) {
canCache <- TRUE
inherited <- FALSE
# The integer vector is numeric!!!
if (is(object, Class)) {
ClassDef <- getClassDef(Class, where)
if (identical(ext, FALSE)) {}
else if (identical(ext, TRUE)) {}
else {
test <- ext@test
# Create S4 coercion method here
asMethod <- .makeAsMethod(ext@coerce, ext@simple,
Class, ClassDef, where)
canCache <- (!is(test, "function")) || identical(body(test),
TRUE)
}
}
if (is.null(asMethod)) {}
else if (canCache)
asMethod <- .asCoerceMethod(asMethod, thisClass,
ClassDef, FALSE, where)
if (is.null(asMethod)) {}
else if (canCache) {
cacheMethod("coerce", sig, asMethod, fdef = coerceFun,
inherited = inherited)
}
}
}
# Use newly created method on object here
if (strict)
asMethod(object)
else asMethod(object, strict = FALSE)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果您只处理基本的原子类型,我会坚持使用基本函数并避免使用methods包;使用的唯一原因methods是处理 S4 对象。
| 归档时间: |
|
| 查看次数: |
761 次 |
| 最近记录: |