2013-03-23 34 views
4

我注意到,定義了as.matrixas.data.frame,因爲S4類 的S3方法使得例如lm (formula, objS4)prcomp (object)開箱即用。如果將它們定義爲S4方法,則這不起作用。`as.matrix`和`as.data.frame` S3方法與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, ...) [email protected]) 
## [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, ...) [email protected] 

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 ([email protected][, 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 ([email protected] [, 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定義一起使用。

+2

這是在''lm''中'data'參數的描述中提到的。 – 2013-03-24 00:07:41

+0

@ G.Grothendieck:我知道可以使用「可對data.frame強制執行的對象」 - 但我期望通過爲'as.data.frame'提供S4方法來啓用此強制功能。我澄清了這個問題。 – cbeleites 2013-03-24 16:47:40

+0

你對S4使用'setAs'嗎? – hadley 2013-03-25 23:48:28

回答

2

我從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通用,並從methods documentation

的S4單獨方法如果S3泛型函數直接調用將不可見。但是,>原始函數和運算符都是例外情況:當且僅當對象是S4對象時,內部C代碼纔會查找S4>方法。在這些示例中,類「myFrame」的[的方法將始終爲此類的對象調用。

+0

謝謝傑米。我可以從該手冊頁添加:**推薦的方法是定義S3方法,並提供與S4方法定義相同的功能。**我希望如果我也提供'setAs',強制兼容性完成。我會再次仔細閱讀方法描述 - 也許我會理解爲什麼直接調用'as.data.frame(object)'或'as.matrix(object)'有效(我不希望從'?methods'文檔),但不是從內部例如'prcomp' ... – cbeleites 2013-03-30 15:34:50