>>>>> "MH" == Michael Hahsler <michael at
hahsler.net>
>>>>> on Mon, 20 Jul 2009 08:57:28 -0500 writes:
MH> Hi, I'm trying to create a new S4 class (myMatrix) which
MH> for now just extends dgCMatrix (from package
MH> Matrix). Then I want to use "[" which is defined in
MH> Matrix.
MH> Out of the box with "[" (defined in Matrix) I lose the
MH> class information and the result is an object of class
MH> dgCMatrix.
Yes, and that's the case for all such methods for "extended"
classes, for S3 / S4 methods alike.
Yes, this is sometimes not what you would like, and on R-devel
we recently had proposals on definining special attributes (for
dataframe / matrix like objects) that
would automatically be preserved in "[i,j]" subsetting.... so
others had had similar wishes / dreams.
As I have learned in similar experience, it's not a good idea to
expect that this happens automatically.
Assume "myMatrix" was meant to always be a square matrix, or
always a symmetric matrix. Then, only *some* "[i,j]" operations
would return a valid "myMatrix"...
For such reasons, indeed, it's you who must provide methods for
your class. Of couese these methods will typically call the
"upper class" method, possibly via callNextMethod(.), or
{my historical preference} directly.
MH> If I specify a "["-method for myMatrix, it is
MH> not used because a signature from Matrix seems to fit
MH> better.
Yes, Matrix" has many methods for "[", for good reasons,
but if you define your methods "correctly",
things are solved easily, see below
MH> However, the most important part of the
MH> signature is the class of x (all else have ANY). Is
MH> there a way to specify a single "["-method do make it
MH> work for myClass?
a single method is not sufficient; "[" is a generic
function with several signauture arguments, on which dispatch
can happen.
And note, that "[" is particularly delicate :
The code (well, the one in "Matrix") must be able to distinguish
between M[ i,]
and M[ i ]
Here's a working solution:
---------------------------------------------------------------
library("Matrix")
setClass("myMatrix", contains="dgCMatrix")
M <- as(Diagonal(x = 1:7), "CsparseMatrix")
(my <- as(as(M, "dgCMatrix"), "myMatrix"))
## here I lose the class "myMatrix"
class(my[1:2,])
## [1] "dgCMatrix"
## make sure [ keeps the class
if(FALSE)# not really needed
setMethod("[", signature(x = "myMatrix"), ## (ANY,ANY...)
function(x, i, j, ..., drop)
as(as(x,"dgCMatrix")[i, j, ..., drop],
"myMatrix"))
setMethod("[", signature(x = "myMatrix",
i="index", j="index", drop="logical"),
function(x, i, j, ..., drop)
as(as(x,"dgCMatrix")[i, j, drop=drop],
"myMatrix"))
setMethod("[", signature(x = "myMatrix",
i="index", j = "missing", drop="logical"),
function(x, i, j, ..., drop)
as(as(x,"dgCMatrix")[i, , drop=drop], "myMatrix"))
setMethod("[", signature(x = "myMatrix", i =
"missing", j="index",drop="logical"),
function(x, i, j, ..., drop)
as(as(x,"dgCMatrix")[ , j, drop=drop],
"myMatrix"))
head(my, 2) ## perfect
my[3,3,drop=FALSE] # ditto
my[, 2:4] # ditto
---------------------------------------------------------------
Note that the three method definitions use slightly different
function bodies: When an argument is "missing", it's not a good
idea to pass it again to the generic "[" which then again would
like to do method dispatch on that missing...
Also, if you replace "index" (the indexing class introduced in
'Matrix", but more generally interesting) by "ANY",
you need another methods definition in order to match to you
"myMatrix" class first, before any of the many specific methods
in "Matrix".....
Note further, that at the DSC 2007, I already noted a similar
situation and had prposed back then, that it would be desirable
to allow the programmer to more closely to specify method
dispatch in a case like yours: We would want to specify that
for method dispatch, the class of "x" (i.e. "myMatrix" in
your case)
should weight much more than the classes of (i,j,drop).
But something like this has to wait for the future, .....
I hope this helped so far.
>> library("Matrix")
[.......]
>>
>> setClass("myMatrix",
MH> + contains="dgCMatrix"
MH> + )
{{why 3 lines instead of 1 ?}}
MH> [1] "myMatrix"
>>
>> my <- as(as(rbind(1:10,1:10,1:10), "dgCMatrix"),
"myMatrix")
>>
>> ## here I lose the class "myMatrix"
>> class(my[1:2,])
MH> [1] "dgCMatrix"
MH> attr(,"package")
MH> [1] "Matrix"
>>
>> ## make sure [ keeps the class
>> setMethod("[", signature(x = "myMatrix", i =
"ANY", j = "ANY",
MH> + drop = "ANY"),
MH> + function(x, i, j, ..., drop) {
MH> + x<- as(x, "dgCMatrix")[i, j, ..., drop]
MH> + as(x, "myMatrix")
MH> + })
MH> [1] "["
>>
>> ## and now it does not use the method defined above.
>> class(my[1:2,])
MH> Note: Method with signature "Matrix#index#missing#missing"
chosen for
MH> function "[",
MH> target signature "myMatrix#integer#missing#missing".
MH> "myMatrix#ANY#ANY#ANY" would also be valid
MH> Note: Method with signature
"sparseMatrix#index#missing#logical" chosen
MH> for function "[",
MH> target signature "myMatrix#integer#missing#logical".
MH> "myMatrix#ANY#ANY#ANY" would also be valid
MH> [1] "dgCMatrix"
MH> attr(,"package")
MH> [1] "Matrix"
>> sessionInfo()
MH> R version 2.9.1 (2009-06-26)
MH> i486-pc-linux-gnu
MH> locale:
MH>
LC_CTYPE=en_US.UTF-8;LC_NUMERIC=C;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=C;LC_MESSAGES=en_US.UTF-8;LC_PAPER=en_US.UTF-8;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=en_US.UTF-8;LC_IDENTIFICATION=C
MH> attached base packages:
MH> [1] stats graphics grDevices utils datasets methods base
MH> other attached packages:
MH> [1] Matrix_0.999375-29 lattice_0.17-25
MH> loaded via a namespace (and not attached):
MH> [1] grid_2.9.1
MH> --
MH> Michael Hahsler
MH> email: michael at hahsler.net
MH> web: http://michael.hahsler.net
MH> ______________________________________________
MH> R-help at r-project.org mailing list
MH> https://stat.ethz.ch/mailman/listinfo/r-help
MH> PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
MH> and provide commented, minimal, self-contained, reproducible code.