2012-10-05 49 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()'的版本。這不是你想要的,還是我感到困惑? (不是相互排斥的可能性,我知道...) –