2012-10-05 37 views
4

'sparcl'包在标准'stat'包中使用'kmeans'功能。我想让它使用我自己的kmeans ++实现。要做到这一点替换R中内置函数的定义?

一种方式是在SPARCL包本身编辑代码。我宁愿避免这种情况,因为它会很麻烦,因为我不知道如何在R中安装编辑后的代码。

不幸的是,superassignment运算符“< < - ”不起作用:

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

既没有 “分配”:

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 

所以编辑包代码的唯一途径?

谢谢!

+1

你可以用'trace'做这个吗? –

+0

你想替换旧版本的原因是什么,而不是仅仅写一个新版本,而是使用那个版本呢? – Dason

+4

创建自己版本的(导出)函数调用'kmeans'并更改这些实例以便它们调用您自己的自定义函数不是更容易吗? (也许这就是@Dason所说的......?) – joran

回答

2

在进一步的思考(和重新阅读您的问题后),这里有一个简单的解决方案,应该为你工作。

您需要做的就是在全球环境中将编辑后的kmeans()版本分配给kmeans。换句话说,在命令行中执行此操作:

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) 

这工作,因为KMeansSparseCluster()(和package:sparcl调用任何其它功能)寻找在namespace:sparclkmeans第一然后imports:sparcl然后namespace:base,然后在.GlobalEnv,它会发现你重新定义kmeans它得到了一个在package:stats之前。再看看自己,试试这个:

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 

得很漂亮,从使用kmeans()不会被你的版本被打乱,因为他们将在自己的命名空间找到kmeans,符号搜索之前的统计数据包功能永远走向全球环境。

+0

@JoshOBrien:这个包是不是特意从stats包中导入'kmeans',所以它会在'imports:sparcl'中?那将是“正确”的方式,是的? – Aaron

+0

@Aaron - 我同意:这将是正确的做法,但这不是Sparcl的作者所做的。我检查了'进口:sparcl',它是空的。不过,你的大点是不错的。如果程序包作者将'import(“stats”)'放入其NAMESPACE文件中,此解决方案将不起作用。 –

+0

感谢您的更新,乔希。尼斯想要检查'进口:sparcl'中的内容。 – Aaron

6

如果你想一个交互式会话期间编辑功能的身体(而不是它的参数),你可以使用trace(),像这样:

trace("kmeans", edit=TRUE) 

然后,在弹出的编辑器,编辑看起来像这样(例如):

function (x, centers, iter.max = 10, nstart = 1, algorithm = c("Hartigan-Wong", 
"Lloyd", "Forgy", "MacQueen")) 
{ 
    plot(rnorm(99), col = "red") 
} 

保存编辑的函数定义,然后退出编辑器。

回到R命令行,您可以查看编辑功能,并尝试一下:

body(kmeans) # To view the tracing code 
kmeans()  # To use the edited function 

最后,要恢复到未编辑的功能,只是做untrace("kmeans")。 (我一般喜欢用trace()assignInNamespace()和朋友,因为untrace()使得它很容易撤消更改。)

+0

谢谢,我不知道trace()。虽然我不认为它完全解决了我的问题,因为sparcl软件包对kmeans的不同功能进行了大量的调用...... – martin

+1

@martas也许只需抓住包的源代码,使用一个好的文本编辑器即可改变所有kmeans调用的实例不会花费太多时间,然后在本地重新生成包。我认为人们对于涉及覆盖统计信息包代码本身的解决方案只是有点怀疑,你可能会后悔。 – joran

+2

'trace()'编辑'namespace:stats'中的函数,因此它将编辑任何调用它的函数看到的'kmeans()'的版本。这不是你想要的,还是我感到困惑? (不是相互排斥的可能性,我知道...) –