Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace definition of built-in function in R?

The 'sparcl' package uses the 'kmeans' function in the standard 'stat' package. I want to make it use my own implementation of kmeans++ instead.

One way to do this would be to edit the code in the sparcl package itself. I'd prefer to avoid this, both because it would be messy and because I'm not sure how I would then install that edited code in R.

Unfortunately, the superassignment operator "<<-" doesn't work:

> kmeans <<- function(x) print("hi!")
Error: cannot change value of locked binding for 'kmeans'

neither does "assign":

assign("kmeans",function(x) {print("HI THERE!"); return(FALSE)},pos="package:sparcl")
Error in assign("is.null", function(x) { : 
  cannot add bindings to a locked environment

So is editing the package code the only way?

Thanks!

like image 659
martin Avatar asked Oct 05 '12 14:10

martin


1 Answers

On further thought (and after re-reading your question), here's a simple solution that should work for you.

All you need to do is to assign your edited version of kmeans() to the symbol kmeans in the global environment. In other words, at the command line do this:

kmeans <- function(...) plot(rnorm(99), col="red") # but using your own edits

## Then run an example from ?KMeansSparseCluster to see that it works.
library(sparcl)
x <- matrix(rnorm(50*300),ncol=300)
x[1:25,1:50] <- x[1:25,1:50]+1
x <- scale(x, TRUE, TRUE)
KMeansSparseCluster.permute(x,K=2,wbounds=seq(3,9,len=15),nperms=5)

This works because KMeansSparseCluster() (and calls to any other functions in package:sparcl) look for kmeans first in namespace:sparcl, then in imports:sparcl, then in namespace:base, and then in .GlobalEnv, where it'll find your redefined kmeans before it gets to the one in package:stats. To have a look yourself, try this:

parent.env(asNamespace("sparcl"))
parent.env(parent.env(asNamespace("sparcl")))
parent.env(parent.env(parent.env(asNamespace("sparcl"))))
## etc., also wrapping any of the environments above in calls to ls() 
## to see what's in 'em

Nicely, functions from the stats package that use kmeans() won't be disrupted by your version, because they will find kmeans in their own namespace, before the symbol-search ever gets to the global environment.

like image 143
Josh O'Brien Avatar answered Sep 20 '22 03:09

Josh O'Brien