Is it possible to call S4 method directly? - r

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

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).

Related

How to capture particular warning message and execute call

Lately when I run my code that uses coxph in the survival package
coxph(frml,data = data), I am now getting warning messages of the following type
1: In model.matrix.default(Terms, mf, contrasts = contrast.arg) :
partial argument match of 'contrasts' to 'contrasts.arg'
2: In seq.default(along = temp) :
partial argument match of 'along' to 'along.with'"
I'm not exactly sure why all of a sudden these partial argument match warnings started popping up, but I don't think they effect me.
However, when I get the following warning message, I want coxph(frml,data = data) = NA
3: In fitter(X, Y, strats, offset, init, control, weights = weights, :
Loglik converged before variable 2 ; beta may be infinite.
6: In coxph(frml, data = data) :
X matrix deemed to be singular; variable 1 3 4
I used tryCatch when I wasn't getting the partial argument match warning using this code where if the nested tryCatch got either a warning or error message it would return NA
coxphfit = tryCatch(tryCatch(coxph(frml,data = data), error=function(w) return(NA)), warning=function(w) return(NA))
However, now that I am getting the partial argument match warnings, I need to only return an NA if there is an error or if I get the above warning messages 3 and 4 . Any idea about how to capture these particular warning messages and return an NA in those instances?
It's actually interesting question, if you are looking for quick and dirty way of capturing warnings you could simply do:
withCallingHandlers({
warning("hello")
1 + 2
}, warning = function(w) {
w ->> w
}) -> res
In this example the object w created in parent environment would be:
>> w
<simpleWarning in withCallingHandlers({ warning("hello") 1 + 2}, warning = function(w) { w <<- w}): hello>
You could then interrogate it:
grepl(x = w$message, pattern = "hello")
# [1] TRUE
as
>> w$message
# [1] "hello"
Object res would contain your desired results:
>> res
[1] 3
It's not the super tidy way but I reckon you could always reference object w and check if the warning message has the phrase you are interested in.

evaluation inside of test_that call

I am trying to write some unit tests for my package and having difficulty getting a test of the gls function from nlme to work. MWE:
library(testthat)
library(nlme)
data(Ovary, package = "nlme")
test_that("getData works.", {
re_order <- sample(nrow(Ovary))
egg_scramble <- Ovary[re_order,]
gls_scramble <- gls(follicles ~ sin(2*pi*Time) + cos(2*pi*Time),
data = egg_scramble)
dat <- getData(gls_scramble)
expect_identical(egg_scramble, dat)
})
For some reason, the getData call cannot find the data within the test environment. Here is the the traceback:
Error: Test failed: 'getData works.'
Not expected: object 'egg_scramble' not found
1: withCallingHandlers(eval(code, new_test_environment), error = capture_calls)
2: eval(code, new_test_environment)
3: eval(expr, envir, enclos)
4: getData(gls_scramble) at :6
5: getData.gls(gls_scramble)
6: eval(if ("data" %in% names(object)) object$data else mCall$data)
7: eval(expr, envir, enclos).
And yet, evaluating the same code outside of test_that does not lead to an error:
re_order <- sample(nrow(Ovary))
egg_scramble <- Ovary[re_order,]
gls_scramble <- gls(follicles ~ sin(2*pi*Time) + cos(2*pi*Time),
data = egg_scramble)
dat <- getData(gls_scramble)
identical(dat, egg_scramble)

traceback() returns useless information for error happened during source()

I am surprised by how hard it is to find where the error happened exactly in R when I am sourcing a file. For example:
> source('Data-Generation.R')
... # some output here
Error in as.matrix(X) %*% coefs[ix_X] : non-conformable arguments
At least in this case, I can find where it is by searching for it because I have as.matrix(X) %*% coefs[ix_X] only once in my code. Anyway, if I try to pinpoint where it happened with traceback():
> traceback()
4: eval(expr, envir, enclos)
3: eval(ei, envir)
2: withVisible(eval(ei, envir))
1: source("Data-Generation.R")
which is useless information.
Am I doing something wrong?
Edited: I am looking for a solution which will produce a message that Python would yield:
$ python .\test.py
1
Traceback (most recent call last):
File ".\test.py", line 5, in <module>
1/0
ZeroDivisionError: integer division or modulo by zero
Set echo = TRUE:
source(textConnection("i <- 1
y*x
3+4"), echo=TRUE)
#> i <- 1
#
#> y*x
#Error in eval(expr, envir, enclos) : object 'y' not found
verbose = TRUE might also be useful:
source(textConnection("i <- 1
y*x
3+4"), verbose=TRUE)
#'envir' chosen:<environment: R_GlobalEnv>
#--> parsed 3 expressions; now eval(.)ing them:
#
#>>>> eval(expression_nr. 1 )
# =================
#
#> i <- 1
#curr.fun: symbol <-
# .. after ‘expression(i <- 1)’
#
#>>>> eval(expression_nr. 2 )
# =================
#
#> y*x
#Error in eval(expr, envir, enclos) : object 'y' not found

Why can't I vectorize source_url in knitr?

I am trying to vectorize this call to source_url, in order to load some functions from GitHub:
library(devtools)
# Find ggnet functions.
fun = c("ggnet.R", "functions.R")
fun = paste0("https://raw.github.com/briatte/ggnet/master/", fun)
# Load ggnet functions.
source_url(fun[1], prompt = FALSE)
source_url(fun[2], prompt = FALSE)
The last two lines should be able to work in a lapply call, but for some reason, this won't work from knitr: to have this code work when I process a Rmd document to HTML, I have to call source_url twice.
The same error shows up with source_url from devtools and with the one from downloader: somehwere in my code, an object of type closure is not subsettable.
I suspect that this has something to do with SHA; any explanation would be most welcome.
It has nothing to do with knitr or devtools or vectorization. It is just an error in your(?) code, and it is fairly easy to find it out using traceback().
> library(devtools)
> # Find ggnet functions.
> fun = c("ggnet.R", "functions.R")
> fun = paste0("https://raw.github.com/briatte/ggnet/master/", fun)
> # Load ggnet functions.
> source_url(fun[1], prompt = FALSE)
SHA-1 hash of file is 2c731cbdf4a670170fb5298f7870c93677e95c7b
> source_url(fun[2], prompt = FALSE)
SHA-1 hash of file is d7d466413f9ddddc1d71982dada34e291454efcb
Error in df$Source : object of type 'closure' is not subsettable
> traceback()
7: which(df$Source == x) at file34af6f0b0be5#14
6: who.is.followed.by(df, "JacquesBompard") at file34af6f0b0be5#19
5: eval(expr, envir, enclos)
4: eval(ei, envir)
3: withVisible(eval(ei, envir))
2: source(temp_file, ...)
1: source_url(fun[2], prompt = FALSE)
You used df in the code, and df is a function in the stats package (density of the F distribution). I know you probably mean a data frame, but you did not declare that in the code.

What arguments were passed to the functions in the traceback?

In R, if execution stops because of an error, I can evaluate traceback() to see which function the error occurred in, which function was that function called from, etc. It'll give something like this:
8: ar.yw.default(x, aic = aic, order.max = order.max, na.action = na.action,
series = series, ...)
7: ar.yw(x, aic = aic, order.max = order.max, na.action = na.action,
series = series, ...)
6: ar(x[, i], aic = TRUE)
5: spectrum0.ar(x)
4: effectiveSize(x)
Is there a way to find what arguments were passed to these functions? In this case, I'd like to know what arguments were passed to effectiveSize(), i.e. what is x.
The error does not occur in my own code, but in a package function. Being new to R, I'm a bit lost.
Not knowing how to do this properly, I tried to find the package function's definition and modify it, but where the source file should be I only find an .rdb file. I assume this is something byte-compiled.
I'd suggest setting options(error=recover) and then running the offending code again. This time, when an error is encountered, you'll be thrown into an interactive debugging environment in which you are offered a choice of frames to investigate. It will look much like what traceback() gives you, except that you can type 7 to enter the evaluation environment of call 7 on the call stack. Typing ls() once you've entered a frame will give you the list of its arguments.
An example (based on that in ?traceback) is probably the best way to show this:
foo <- function(x) { print(1); bar(2) }
bar <- function(x) { x + a.variable.which.does.not.exist }
## First with traceback()
foo(2) # gives a strange error
# [1] 1
# Error in bar(2) : object 'a.variable.which.does.not.exist' not found
traceback()
# 2: bar(2) at #1
# 1: foo(2)
## Then with options(error=recover)
options(error=recover)
foo(2)
# [1] 1
# Error in bar(2) : object 'a.variable.which.does.not.exist' not found
#
# Enter a frame number, or 0 to exit
#
# 1: foo(2)
# 2: #1: bar(2)
Selection: 1
# Called from: top level
Browse[1]> ls()
# [1] "x"
Browse[1]> x
# [1] 2
Browse[1]> ## Just press return here to go back to the numbered list of envts.
#
# Enter a frame number, or 0 to exit
#
# 1: foo(2)
# 2: #1: bar(2)
R has many helpful debugging tools, most of which are discussed in the answers to this SO question from a few years back.
You can use trace() to tag or label a function as requiring a "detour" to another function, the logical choice being browser().
?trace
?browser
> trace(mean)
> mean(1:4)
trace: mean(1:4)
[1] 2.5
So that just displayed the call. This next mini-session shows trace actually detouring into the browser:
> trace(mean, browser)
Tracing function "mean" in package "base"
[1] "mean"
> mean(1:4)
Tracing mean(1:4) on entry
Called from: eval(expr, envir, enclos)
Browse[1]> x #once in the browser you can see what values are there
[1] 1 2 3 4
Browse[1]>
[1] 2.5
> untrace(mean)
Untracing function "mean" in package "base"
As far as seeing what is in a function, if it is exported, you can simply type its name at the console. If it is not exported then use: getAnywhere(fn_name)

Resources