Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么对于整数向量x,as(x,“numeric”会触发加载额外的S4强制方法?_R_S4 - Fatal编程技术网

为什么对于整数向量x,as(x,“numeric”会触发加载额外的S4强制方法?

为什么对于整数向量x,as(x,“numeric”会触发加载额外的S4强制方法?,r,s4,R,S4,虽然我的问题与之相关,但我怀疑它的答案将与R的S4对象系统的详细工作有关 我所期望的是: (TLDR;——所有指示都是as(4L,“numeric”)应该分派给一个函数,该函数的主体使用as.numeric(4L)将其转换为“numeric”向量。) 无论何时使用as(object,Class)将对象转换为所需的类,都会触发对强制()的幕后调用强制()。要查看所有可用S4concure()方法的列表,可以运行showMethods(“concure”) 这样做表明只有一种方法可以转换为类“num

虽然我的问题与之相关,但我怀疑它的答案将与R的S4对象系统的详细工作有关

我所期望的是: (TLDR;——所有指示都是
as(4L,“numeric”)
应该分派给一个函数,该函数的主体使用
as.numeric(4L)
将其转换为
“numeric”
向量。)

无论何时使用
as(object,Class)
将对象转换为所需的
,都会触发对
强制()的幕后调用<代码>强制()。要查看所有可用S4
concure()
方法的列表,可以运行
showMethods(“concure”)

这样做表明只有一种方法可以转换为类
“numeric”
。这是一个签名为
从=“ANY”到=“numeric”

该方法使用
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"
实际发生的情况: (TLDR;事实上,调用
as(4L,“numeric”)
加载并分派给一个什么都不做的方法。)

尽管上面提到了所有指示,
as(4L,“numeric”)
不会为签名为
c(“ANY”,“numeric”)
的调用分派到
concure()
方法

这里有两种方法可以说明:

## (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")
我的问题是:
  • 为什么
    as(4L,“numeric”)
    没有为
    signature=c(“ANY”,“numeric”)
    分派到可用的
    强制()
    方法

  • 它如何/为什么向S4方法表添加新方法

  • signature=c(“integer”、“numeric”)
    concure()
    方法的定义来自哪里(在R的源代码或其他地方)


  • 查看
    as()
    的源代码,它有两部分。(为了清晰起见,源代码被缩短了)。首先,它查找
    强制()
    的现有方法,如上所述

    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))
    
    function(对象,类,strict=TRUE,ext=possibleExtends(此类,
    (类别)
    {
    
    这节课我不确定是否能详尽地回答你的问题,但我会尽力的

    as()
    函数的帮助说明:

    函数“as”将“object”转换为类“class”的对象。在此过程中,它应用了一种“强制方法”,使用S4类和方法,但方式有些特殊

    [……]

    假设“对象”不属于所需的类,“as”首先在签名“c”(from=class(object),to=class)的函数“强制”的方法表中查找一个方法,方法选择将以相同的方式进行初始查找

    [……]

    如果找不到任何方法,“as”查找其中一个。首先,如果“Class”或“Class(object)”是另一个的超类,则类定义将包含构造强制方法所需的信息。在通常情况下,子类包含超类(即,具有其所有插槽)方法是通过提取或替换继承的插槽来构造的

    如果您查看
    as()
    函数的代码(要查看它,请在R控制台中键入
    as
    (不带括号!)),您可以看到下面的内容。首先,它会查找
    asMethod
    ,如果找不到,它会尝试构造一个,最后执行它:

    if (strict) 
        asMethod(object)
    else asMethod(object, strict = FALSE)
    
    当您复制粘贴
    as()
    函数的代码并定义自己的函数时—我们称之为
    myas()
    —您可以在刚才提到的
    if(strict)
    上方插入
    print(asMethod)
    ,以获取用于强制的函数。在这种情况下,输出为:

    > myas(4L, 'numeric')
    function (from, to = "numeric", strict = TRUE) 
    if (strict) {
        class(from) <- "numeric"
        from
    } else from
    <environment: namespace:methods>
    attr(,"target")
    An object of class “signature”
         from        to 
    "integer" "numeric" 
    attr(,"defined")
    An object of class “signature”
         from        to 
    "integer" "numeric" 
    attr(,"generic")
    [1] "coerce"
    attr(,"generic")attr(,"package")
    [1] "methods"
    attr(,"class")
    [1] "MethodDefinition"
    attr(,"class")attr(,"package")
    [1] "methods"
    attr(,"source")
    [1] "function (from, to = \"numeric\", strict = TRUE) "
    [2] "if (strict) {"                                    
    [3] "    class(from) <- \"numeric\""                   
    [4] "    from"                                         
    [5] "} else from"                                      
    [1] 4
    
    有趣的是,两者都是“无”。更有趣的是,另一种方式是:

    > x = 4
    > class(x)
    [1] "numeric"
    > class(x) <- 'integer'
    > class(x)
    [1] "integer"
    
    视为.numeric
    : 这是一个通用方法,调用
    as.double()
    ,这就是它“工作”的原因(来自
    as.numeric
    上的R帮助):

    历史上的一个反常现象是,R的浮点向量有两个名称,“double”和“numeric”(以前有“real”)

    “double”是类型的名称。“numeric”是模式的名称,也是隐式类的名称

    关于问题(1)-(3):神奇发生在
    函数顶部的那四行:

    where <- .classEnv(thisClass, mustFind = FALSE)
    coerceFun <- getGeneric("coerce", where = where)
    coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun), inherited = TRUE)
    asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun, coerceMethods, where)
    

    有趣的是,在一个新的R会话中执行
    跟踪(“强制”,signature=c(“整数”,“数字”))
    实际上会跟踪
    signature=c(“任意”,“数字”)
    的方法,并会导致该方法通过对
    的任何后续调用作为(4L,“数字”)
    进行调度(例如)我现在对它的理解是,
    as
    绕过了
    as.numeric
    作为整数,以便与
    is.numeric
    一致(检查类,而不是数据类型),并保持
    integer
    numeric
    的子类的想法在
    中,as.numeric
    指的是存储模式,而不是类,因此在将整数向量的类转换为数值时不应使用它。@MatthewPlourd--我确实听到了你的说法,这听起来似乎是有道理的,但我觉得这是对一个关于这种行为的动机或原理的问题的回答。我基本上对这不是我自己的问题,相反,我试图询问这里发生的事情的机制。(例如,为什么
    signature=c(“integer”、“numeric”)
    的方法不只是包含在
    impress()
    的原始/普通方法表中?如果是的话,我就不会问这个问题了
    if (strict) 
        asMethod(object)
    else asMethod(object, strict = FALSE)
    
    > myas(4L, 'numeric')
    function (from, to = "numeric", strict = TRUE) 
    if (strict) {
        class(from) <- "numeric"
        from
    } else from
    <environment: namespace:methods>
    attr(,"target")
    An object of class “signature”
         from        to 
    "integer" "numeric" 
    attr(,"defined")
    An object of class “signature”
         from        to 
    "integer" "numeric" 
    attr(,"generic")
    [1] "coerce"
    attr(,"generic")attr(,"package")
    [1] "methods"
    attr(,"class")
    [1] "MethodDefinition"
    attr(,"class")attr(,"package")
    [1] "methods"
    attr(,"source")
    [1] "function (from, to = \"numeric\", strict = TRUE) "
    [2] "if (strict) {"                                    
    [3] "    class(from) <- \"numeric\""                   
    [4] "    from"                                         
    [5] "} else from"                                      
    [1] 4
    
    > # Snippet 1
    > x = 4L
    > x = as(x, 'numeric')
    
    > # Snippet 2
    > x = 4L
    > class(x) <- 'numeric'
    
    > x = 4
    > class(x)
    [1] "numeric"
    > class(x) <- 'integer'
    > class(x)
    [1] "integer"
    
    > x = 4L
    > class(x)
    [1] "integer"
    > is.numeric(x)
    [1] TRUE
    
    where <- .classEnv(thisClass, mustFind = FALSE)
    coerceFun <- getGeneric("coerce", where = where)
    coerceMethods <- .getMethodsTable(coerceFun, environment(coerceFun), inherited = TRUE)
    asMethod <- .quickCoerceSelect(thisClass, Class, coerceFun, coerceMethods, where)