Заменить определение встроенной функции в R?

Пакет 'sparcl' использует функцию 'kmeans' в стандартном пакете 'stat'. Я хочу, чтобы вместо этого я использовал собственную реализацию 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 ответа

Решение

Если подумать (и перечитать ваш вопрос), вот простое решение, которое должно работать на вас.

Все, что вам нужно сделать, это назначить вашу отредактированную версию 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затем в 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 в их собственном пространстве имен, прежде чем поиск символов попадет в глобальную среду.

Если вы хотите отредактировать тело функции (но не ее аргументы) во время интерактивного сеанса, вы можете использовать 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() делает так легко отменить изменения.)

Другие вопросы по тегам