替换R中内置函数的定义?

时间:2012-10-05 14:46:42

标签: r function package

'sparcl'包使用标准'stat'包中的'kmeans'功能。我想让它使用我自己的kmeans ++实现。

执行此操作的一种方法是编辑sparcl包本身中的代码。我宁愿避免这种情况,因为它会很混乱,因为我不确定如何在R中安装编辑过的代码。

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

> 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

编辑包代码是唯一的方法吗?

谢谢!

2 个答案:

答案 0 :(得分:7)

如果您确实想在交互式会话期间编辑函数的正文(但不是其参数),可以使用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()可以轻松撤消更改。)

答案 1 :(得分: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中的任何其他功能的调用)在kmeans中查找namespace:sparcl 然后在imports:sparcl,在<{1}}中然后,然后在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()的stats包中的函数不会被您的版本中断,因为在符号搜索到达全局之前,他们会在自己的命名空间中找到kmeans环境。