Mohit Verma
Mohit Verma

Reputation: 2089

Is it possible to call S4 method directly?

Trying to build a gausspr model and using predict to predict the output. Copying code from predict.gausspr documentation.

data(promotergene)

## create test and training set
ind <- sample(1:dim(promotergene)[1],20)
genetrain <- promotergene[-ind, ]
genetest <- promotergene[ind, ]

## train a support vector machine
gene <- gausspr(Class~.,data=genetrain,kernel="rbfdot",
                kpar=list(sigma=0.015))

## predict gene type probabilities on the test set
genetype <- predict(gene,genetest,type="probabilities")

This works fine. Now, when i try to call predict.gausspr directly it's failing. Is it possible to call this S4 method directly ? Also, is this case with any S4 method or something special in this case ?

> genetype <- predict.gausspr(gene,genetest,type="probabilities")
Error: could not find function "predict.gausspr"

kernlab package is loaded properly and am able to do ?predict.gausspr and see the notes

Upvotes: 1

Views: 495

Answers (1)

Martin Morgan
Martin Morgan

Reputation: 46856

I guess you mean the gausspr() function from the kernlab package. Using the snippet from ?gausspr I see

library(kernlab)
data(iris)
test <- gausspr(Species~., data=iris, var=2)
predict(test, iris[,-5])

test is indeed an S4 object

> isS4(test)
[1] TRUE
> class(test)
[1] "gausspr"
attr(,"package")
[1] "kernlab"

Discovering S4 methods

S4 methods are discovered using showMethods() and selectMethod() (output edited for brevity)

> showMethods("predict")
Function: predict (package stats)
object="ANY"
object="gausspr"
object="kfa"
object="kha"
object="kpca"
object="kqr"
object="ksvm"
object="lssvm"
object="onlearn"
object="rvm"

> showMethods(class=class(test), where=search())
Function: alphaindex (package kernlab)
object="gausspr"

...
Function: predict (package stats)
object="gausspr"
...


> selectMethod("predict", class    Method Definition:

function (object, ...) 
{
    .local <- function (object, newdata, type = "response", coupler = "minpair") 
    {
        sc <- 0
        type <- match.arg(type, c("response", "probabilities", 
            "votes", "variance"))
...

If there was no relevant predict,gausspr method, then we would end up at predict,ANY-method, which actually invokes the S3 methods discovered by methods("predict").

The help page is discovered with

?"predict,gausspr-method"

Debugging S4 methods

traceback / recover

If a method fails and you'd like to debug it, then usually the simplest thing to do is to use ?traceback to find out where the error occurs, and ?recover to identify the problem in more detail. Here's an error

> predict(test, mtcars)
Error in eval(expr, envir, enclos) : object 'Sepal.Length' not found

and we can see the 'call stack' from 1 (the generic 'predict') to 2 (the method 'predict,gausspr-mehtod') to 3 (the .local function, defined inside the gausspr method), etc.

> traceback()
9: eval(expr, envir, enclos)
8: eval(predvars, data, env)
7: model.frame.default(object, data, xlev = xlev)
6: model.frame(object, data, xlev = xlev)
5: model.matrix.default(delete.response(terms(object)), as.data.frame(newdata), 
       na.action = na.action)
4: model.matrix(delete.response(terms(object)), as.data.frame(newdata), 
       na.action = na.action)
3: .local(object, ...)
2: predict(test, mtcars)
1: predict(test, mtcars)

Set the error option (see ?options) to recover and try again, choosing the frame number inside the .local function to be in the body of the method.

> options(error=recover)
> predict(test, mtcars)
Error in eval(expr, envir, enclos) : object 'Sepal.Length' not found

Enter a frame number, or 0 to exit   

1: predict(test, mtcars)
2: predict(test, mtcars)
3: .local(object, ...)
4: model.matrix(delete.response(terms(object)), as.data.frame(newdata), na.act
5: model.matrix.default(delete.response(terms(object)), as.data.frame(newdata)
6: model.frame(object, data, xlev = xlev)
7: model.frame.default(object, data, xlev = xlev)
8: eval(predvars, data, env)
9: eval(expr, envir, enclos)

Selection: 3
Called from: eval(predvars, data, env)
Browse[1]> ls()
[1] "coupler" "ncols"   "newdata" "nrows"   "object"  "oldco"   "sc"     
[8] "type" 

Restore normal error behavior with options(error=NULL).

debug / trace

There are a couple of things to do to debug S4 methods. The first is to use the debugger on the selected methods

debug(selectMethod("predict", class(test)))

The second is to trace the method

trace("predict", browser, signature=class(test))

(stop tracing with untrace("predict", signature=class(test))

In this particular case you'll see that the body of the function is in a nested function called .local. Setting the debugger on the outer function is not enough, instead one needs to break in the outer function, then step through until .local has been defined but not evaluated, and set the debugger on .local, like (editing the output for brevity)

> trace(predict, browser, signature=class(test))
Tracing specified method for function "predict" in environment
<namespace:stats>
Warning: Tracing only in the namespace; to untrace you will need:
untrace("predict", where = getNamespace("stats"))
[1] "predict"
attr(,"package")
[1] "stats"
> predict(test, iris[,-5])
Tracing predict(test, iris[, -5]) on entry 
Called from: eval(expr, envir, enclos)
Browse[1]> n
debug: {
    .local <- function (object, newdata, type = "response", coupler = "minpair") 
    {
        sc <- 0
        type <- match.arg(type, c("response", "probabilities", 
...
Browse[2]> n
debug: .local(object, ...)
Browse[2]> debug(.local)
Browse[2]> n
debugging in: .local(object, ...)
debug: {
    sc <- 0
    type <- match.arg(type, c("response", "probabilities", "votes", 
...
Browse[3]> 

The author of the kernlab package did not provide an S3-style function predict.gausspr, even though the S4 guidelines (?setMethod) suggest that they do. This would have simplified debugging, e.g., debug(kernlab:::predict.gausspr).

Upvotes: 2

Related Questions