Методы as.matrix и as.data.frame S3 против методов S4

Я заметил, что определение as.matrix или as.data.frame как методов S3 для класса S4 делает, например. lm (formula, objS4) и prcomp (object) работают из коробки. Это не работает, если они определены как методы S4.

Почему имеет значение, определены ли методы как метод S3 или S4?

Пример для 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  

Поскольку ситуация может быть немного сложной с lm, где принуждение будет происходить только тогда, когда формула вычисляется в среде, созданной из данных, вот более простой случай с тем же поведением:

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

Здесь вызывается stats:::prcomp.default, который начинается с простого x <- as.matrix (x). Это не работает с приведенным выше определением S4, но работает с определением S3.


person cbeleites unhappy with SX    schedule 23.03.2013    source источник
comment
Это упоминается в описании аргумента data в ?lm .   -  person G. Grothendieck    schedule 24.03.2013
comment
@ G.Grothendieck: я знаю, что можно использовать объекты, приводимые к data.frame, но я ожидал, что это приведение можно будет включить, предоставив метод S4 для as.data.frame. Я уточнил вопрос.   -  person cbeleites unhappy with SX    schedule 24.03.2013
comment
Вы используете setAs для S4?   -  person hadley    schedule 26.03.2013
comment
@hadley: setAs включает as (object, "data.frame"), но ни lm, ни prcomp так не работают.   -  person cbeleites unhappy with SX    schedule 26.03.2013
comment
Хорошо, я не был уверен, что as.data.frame попытается использовать метод S4 as, если потребуется. Сбивает с толку, сколько существует механизмов принуждения объектов. Возможно, вы захотите задать этот вопрос на R-devel.   -  person hadley    schedule 27.03.2013


Ответы (1)


Я понял из комментариев, что lm просто явно вызывает as.data.frame. Если вы посмотрите на 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>

Вы увидите, что он вызывает универсальный S3 и из документация по методам

Сам по себе метод S4 не будет виден, если универсальная функция S3 вызывается напрямую. Однако >примитивные функции и операторы являются исключениями: внутренний код C будет искать >методы S4 тогда и только тогда, когда объект является объектом S4. В примерах метод [ для >класса "myFrame" всегда будет вызываться для объектов этого класса.

person jamie.f.olson    schedule 29.03.2013
comment
Спасибо Джейми. Я могу добавить из этой справочной страницы: рекомендуемый подход состоит в том, чтобы определить метод S3, а также предоставить ту же функцию, что и определение метода S4. Я надеюсь, что, если я также предоставлю setAs, совместимость приведения полный. Я еще раз внимательно прочитаю описание методов - возможно, я приду к пониманию, почему прямой вызов as.data.frame (object) или as.matrix (object) работает (я бы этого не ожидал из документации ? methods), но не изнутри, например. prcomp... - person cbeleites unhappy with SX; 30.03.2013