In source code of R randomForest package, I find the following code in grow.R. What's the purpose for UseMethod? Why does function grow not have function definition and just grow.default and grow.randomForest have definition? Is this something related to calling C function in the R package?
grow <- function(x, ...) UseMethod("grow")
grow.default <- function(x, ...)
stop("grow has not been implemented for this class of object")
grow.randomForest <- function(x, how.many, ...) {
y <- update(x, ntree=how.many)
combine(x, y)
}
Also, in the randomForest.R file, I only find the following code. There is randomForest.default.R file too. Why is there no randomForest.randomForest definition like function grow?
"randomForest" <-
function(x, ...)
UseMethod("randomForest")
What's the purpose for UseMethod? Why does function grow not have function definition and just grow.default and grow.randomForest have definition?
I'd suggest reading about S3 dispatch to understand the patterns you see. Advanced R has a chapter on S3. You can also see related questions here on Stack Overflow.
Is this something related to calling C function in the R package?
No.
Why is there no randomForest.randomForest definition like function grow?
This should make sense if you do the recommended reading above. S3 dispatch uses a pattern of function_name.class to call the correct version of the function (method) based on class of the input. You don't give a randomForest object as an input to the randomForest function, so there is no randomForest.randomForest method defined.
grow() does get called on randomForest objects, hence the grow.randomForest() method. Presumably the authors wanted grow() to error early if it gets called on inappropriate input, so the default for other classes is an immediate error, but they still keep dispatch flexible to work with other classes, enabling extensions of the package and nice play with other packages that may have their own grow() implementations.
Related
Consider a simple R function:
#' #importFrom BarPackage Bar
Foo <- function (n, x) {
replicate(1e6, Bar(numeric(n), x))
}
If Bar() is a method, then calling Bar.numeric(numeric(n), x) saves R from having to look up the class of numeric(n); in a real-world example, this shaves about 10% off my run time.
However, Bar.numeric() is a function in a separate package (which I maintain). Roxygen creates export(Bar) and S3method(Bar, numeric) entries in NAMESPACE, but if I add importFrom BarPackage Bar to the FooPackage NAMESPACE and try to run Foo(), I see Warning message: 'Bar.numeric' is not exported by 'namespace:BarPackage' -- as indeed it's not.
It feels like I need to create a separate entry in my NAMESPACE reading export(Bar.numeric), but this feels like a very bad idea (in part because I don't think that Roxygen will do it). Is there any other way of avoiding R having to look up the class of numeric(n) on each call to Bar()?
I know there are related posts, but with insufficient answers. So please answer seriously to this question.
There are two packages ("keithley" and "xantrex") which control two different hardware devices. Therefore, both are independent from each other. Each of them must be initialised separately. So I wrote two methods
init.keithley(inst,...) # in keythley package
and
init.xantrex(inst,...) # in xantrex package
for the generic S3 function init(inst,...). I tried to declare the generic function in the keithley package and in the xantrex package, but then it is masked, once the latter is loaded and the methods where not found any more.
What I tried is the .onAttach()-hook
.onAttach <- function(libname, pkgname)
{
if(!exists("init"))
eval(expression(init <- function(inst,...) UseMethod("init")),envir = .GlobalEnv)
}
But with this it is NOT possible to evaluate the init() function within the package namespace. This can be proofed with the option envir = environment(), which will not work. I also tried setGenericS3() and setGeneric() with always the same result.
The "dirty" solution could be to define a third package and import it, but there must be a clean way to do this.
Where and how should I define the generic function?
Here is the solution:
As I understand, an attached package has three environments (e.g. "package:Xantrex", "namespace:Xantrex" and "imports:Xantrex") the different meaning of these is explained in detail here: Advanced R.
Now, we have to test whether the generic function init() is already there and if not we have to initialize it in the right environment. The following code will do that for us.
.onAttach <- function(libname, pkgname)
{
if(!exists("init",mode = "function"))
eval(expression(init <- function(inst,...) UseMethod("init")),envir = as.environment("package:Xantrex"))
}
The .onAttach-hook, is necessary to guarantee that the different namespaces are initialized. In contrast to that the .onLoad-hook, would be too early. Mention that the expression is evaluated in the package:Xantrex environment, so the generic becomes visible in the search path.
Next to that take care, that your NAMESPACE file will export(init.xantrex) and NOT S3method(init,xantrex). The latter will result an error, because the generic for the method init.xantrex()is not present while building the package.
Best!
Martin
I am trying to understand how the SVM predict function works when using command ksvm from R package kernlab.
I tried the look into the predict function using the following commands:
methods(class="ksvm")
getAnywhere(ksvm:::predict)
However, I get the following output and not the complete predict function:
A single object matching ‘:::’ ‘ksvm’ ‘predict’ was found
It was found in the following places
package:base
namespace:base
with value
function (pkg, name)
{
pkg <- as.character(substitute(pkg))
name <- as.character(substitute(name))
get(name, envir = asNamespace(pkg), inherits = FALSE)
}
<bytecode: 0x00000000088be4f8>
<environment: namespace:base>
Warning message:
In find(x, numeric = TRUE) :
elements of 'what' after the first will be ignored
Can someone help with how to obtain the complete predict function?
Update 1:
Suggestion from misspelled worked fine on predict function for ksvm in kernlab package but doesn't seem to work on svm in e1071 package.
It throws the following error:
> getMethod("predict", "svm")
Error in getMethod("predict", "svm") :
no generic function found for 'predict'
In general, how to know which get method to use?
You were close. I was able to get the function code with getMethod("predict", "ksvm"). This answer describing S4 method dispatch was helpful. View source code for function
Per your updated question, I can get the source code for predict.svm using the ::: function. Specifically with e1071:::predict.svm. The link above also describes this in the section on S3 method dispatch.
There are at least a couple of things going on here. First is that in the former case you are dealing with S4 objects and S3 objects in the latter. The two systems have different method dispatches and different ways to view the source code. Another wrinkle is that the predict.svm function is an invisible function and can only be viewed either with ::: or getAnywhere().
I'm almost certain I've read somewhere how to do this. Instead of having to save the current option (say working directory) to a variable, change the w.d, do an operation, and then revert back to what it was, doing this inside a function akin to "with" relative to attach/detach. A solution just for working directory is what I need now, but there might be a more generic function that does that sort of things? Or ain't it?
So to illustrate... The way it is now:
curdir <- getwd()
setwd("../some/place")
# some operation
setwd(curdir)
The way it is in my wildest dreams:
with.dir("../some/place", # some operation)
I know I could write a function for this, I just have the impression there's something more readily available and generalizable to other parameters too.
Thanks
There is an idiom for this in some of R's base plotting functions
op <- par(no.readonly = TRUE)
# par(blah = stuff)
# plot(stuff)
par(op)
that is so unbelievably crude as to be fully portable to options() and setwd().
Fortunately it's also easy to implement a crude wrapper:
with_dir <- function(dir, expr) {
old_wd <- getwd()
setwd(dir)
result <- evalq(expr)
setwd(old_wd)
result
}
I'm no wizard with nonstandard evaluation so evalq could be unstable somehow. More on NSE in an old write-up by Lumley and also in Wickham's Advanced R, but it's dense stuff and I haven't wrapped my head around it all yet.
edit: as per Ben Bolker's comment, it's probably better to use on.exit for this:
with_dir <- function(dir, expr) {
old_wd <- getwd()
on.exit(setwd(old_wd))
setwd(dir)
evalq(expr)
}
From the R docs:
on.exit records the expression given as its argument as needing to be executed when the current function exits (either naturally or as the result of an error). This is useful for resetting graphical parameters or performing other cleanup actions.
What you're describing depends upon two things: detecting when you enter and leave a particular lexical scope, and defining a behavior to do on entrance and on exit. Python has these, called "Context Managers". This was a big deal when it was released, and many parts of Python's standard library now behave like context managers, and have to define the "enter" and "exit" behavior in explicitly, or by leveraging some clever inheritance scheme.
with.default
function (data, expr, ...)
eval(substitute(expr), data, enclos = parent.frame())
<bytecode: 0x07d02ccc>
<environment: namespace:base>
R's with function works sort of like a context manager, because it can pass scopes around easily. That said, this doesn't give you the "enter" and "exit" operations for free. Especially consider that the current working directory isn't an entry in the current scope, but a state of the R interpreter, which can only be queried or changed by function calls behind the .Internal shield.
You can easily define your own object types to have methods that are context manager-like for the with generic function, as well as writing and registering methods for other types you commonly use, but it is not part of the base R language.
I've noticed some strange behaviour in R reference classes when trying to implement some optimisation algorithm. There seems to be some behind-the-scenes parsing magic involved in initialising methods in a particular which makes it difficult to work with anonymous functions.
Here's an example that illustrates the difficulty: I define a function to optimise (f_opt), a function that runs optim on it, and a reference class that has these two as methods. The odd behaviour will be clearer in the code
f_opt <- function(x) (t(x)%*%x)
do_optim_opt <- function(x) optim(x,f)
do_optim2_opt <- function(x)
{
f(x) #Pointless extra evaluation
optim(x,f)
}
optClass <- setRefClass("optClass",methods=list(do_optim=do_optim_opt,
do_optim2=do_optim2_opt,
f=f_opt))
oc <- optClass$new()
oc$do_optim(rep(0,2)) #Doesn't work: Error in function (par) : object 'f' not found
oc$do_optim2(rep(0,2)) #Works.
oc$do_optim(rep(0,2)) #Parsing magic has presumably happened, and now this works too.
Is it just me, or does this look like a bug to other people too?
This post in R-devel seems relevant, with workaround
do_optim_opt <- function(x, f) optim(x, .self$f)
Seems worth a post to R-devel.