`as.matrix` and` as.data.frame` S3 methods compared to S4 methods

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

Why does it matter if methods are defined as S3 or S4 methods?

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 

Since the situation can be a little complicated with lm , where coercion will occur only when calculating the formula in an environment built from data, here is a simpler case with the same behavior:

 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 

This calls stats:::prcomp.default , which starts with a simple x <- as.matrix (x) . This is not done using the definition of S4 described above, but works with the definition of S3.

+4
source share
1 answer

I take this from the comments that lm just 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 will see what it calls S3 generic and from the documentation methods

Only one S4 method will not be considered if the calling function S3 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> of the class "myFrame" will always be called for objects of this class.

+2
source

All Articles