`as.matrix` and `as.data.frame` S3 methods vs. S4 methods

社会主义新天地 提交于 2019-12-10 13:57:07

问题


I noticed that defining as.matrix or as.data.frame as S3 methods for an S4 class makes e.g. lm (formula, objS4) and prcomp (object) work out of the box. This doesn't work if they are defined as S4 methods.

Why does it matter whether the methods are defined as S3 or S4 method?

Example for as.data.frame:

setClass ("exampleclass", representation (x = "data.frame"))
object <- new ("exampleclass", x = iris)

setMethod ("as.data.frame", signature="exampleclass", definition= function (x, ...) x@x )
## [1] "as.data.frame"

as.data.frame (object)
## Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
## 1            5.1         3.5          1.4         0.2     setosa
## 2            4.9         3.0          1.4         0.2     setosa
## 3            4.7         3.2          1.3         0.2     setosa
## ...snip...

lm (Petal.Length ~ Petal.Width, object)
## error in as.data.frame.default(data) : 
##   cannot coerce class 'structure("exampleclass", package = ".GlobalEnv")' into a data.frame

as.data.frame.exampleclass <- function (x, ...) x@x

lm (Petal.Length ~ Petal.Width, object)
## Call:
##   lm(formula = Petal.Length ~ Petal.Width, data = object)
## 
## Coefficients:
##   (Intercept)  Petal.Width  
## 1.084        2.230  

As the situation may be a bit complicated with lm where the coercion will only occur when the formula is evaluated in an environment constructed from the data, here is a more simple case whith the same behaviour:

setMethod ("as.matrix", signature="exampleclass", definition= function (x, ...) as.matrix (x@x[, 1:4]) )
prcomp (object)
## error in as.vector(data) : 
##   No method to coerce this S4 class into a vector
as.matrix.exampleclass <- function (x, ...) as.matrix (x@x [, 1:4])
prcomp (object)
##   Standard deviations:
##     [1] 2.0562689 0.4926162 0.2796596 0.1543862
##   
## Rotation:
##   PC1         PC2         PC3        PC4
## Sepal.Length  0.36138659 -0.65658877  0.58202985  0.3154872
## Sepal.Width  -0.08452251 -0.73016143 -0.59791083 -0.3197231
## Petal.Length  0.85667061  0.17337266 -0.07623608 -0.4798390
## Petal.Width   0.35828920  0.07548102 -0.54583143  0.7536574

Here, stats:::prcomp.default is called, which starts with a plain x <- as.matrix (x). This fails with the above S4 definition, but works with the S3 definition.


回答1:


I take it from the comments that lm simply calls as.data.frame explicitly. If you look at as.data.frame:

> as.data.frame
function (x, row.names = NULL, optional = FALSE, ...) 
{
    if (is.null(x)) 
        return(as.data.frame(list()))
    UseMethod("as.data.frame")
}
<bytecode: 0x29140b8>
<environment: namespace:base>

You'll see that it calls the S3 generic, and from the methods documentation

An S4 method alone will not be seen if the S3 generic function is called directly. However, >primitive functions and operators are exceptions: The internal C code will look for S4 >methods if and only if the object is an S4 object. In the examples, the method for [ for >class "myFrame" will always be called for objects of this class.



来源:https://stackoverflow.com/questions/15593021/as-matrix-and-as-data-frame-s3-methods-vs-s4-methods

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!