2012-02-22 10 views
6

Si consideri il seguente codice R:R: funzioni annullando momentaneamente e la portata/namespace

local({ 
    lm <- function(x) x^2 
    lm(10) 
}) 

Questo sostituisce temporaneamente la funzione lm, ma una volta che è stato eseguito local sarà "essere tornato alla normalità". Mi chiedo il motivo per cui lo stesso approccio non sembra funzionare in questo prossimo semplice esempio:

require(car) 
model <- lm(len ~ dose, data=ToothGrowth) 
local({ 
    vcov <- function(x) hccm(x) #robust var-cov matrix 
    confint(model) # confint will call vcov, but not the above one. 
}) 

La funzione confint utilizza la funzione vcov per ottenere errori standard per i coefficienti, e l'idea è quella di utilizzare un robusto Var- cov matrix ignorando temporaneamente vcov, senza eseguire "manualmente" o alterare le funzioni.

Sia vcov che confint sono funzioni generiche, non so se questo è il motivo per cui non funziona come previsto. Non è l'esempio specifico a cui sono interessato in quanto tale; piuttosto la lezione concettuale. Si tratta di uno spazio dei nomi o di un "problema" dell'ambito?

risposta

4

mostriamo come fare questo utilizzando oggetti proxy (vedi sezione Proxy di questo document), prima con il proto package e poi senza:

1) proto. Poiché confint.lm chiama vcov, è necessario garantire che (a) la nuova sostituzione per vcov sia nell'ambiente confint.lm modificato e (b) la confint.lm modificata possa accedere agli oggetti dal suo originale. (Per esempio, confint.lm chiama la funzione nascosta format.perc in statistiche, quindi se non ci organizziamo per il secondo punto per essere vero che la funzione nascosto non è stato possibile accedere.)

Per eseguire quanto sopra facciamo una nuova confint.lm che è il lo stesso eccetto che ha un nuovo ambiente (l'ambiente proxy) che contiene il nostro replacment vcov e il cui genitore a sua volta è l'ambiente originale confint.lm. Sotto, l'ambiente proxy è implementato come un oggetto proto dove gli elementi chiave da sapere qui sono: (a) gli oggetti proto sono ambienti e (b) posizionando una funzione in un oggetto proto nel modo in cui viene mostrato il suo ambiente per essere quell'oggetto proto . Inoltre, per evitare problemi dall'invio S3 di confint a confint.lm, chiamiamo direttamente il metodo confint.lm.

Anche se il hccm non sembra avere alcun risultato diverso qui possiamo verificare che era gestito da notare l'uscita del trace:

library(car) 
library(proto) 

trace(hccm) 

model <- lm(len ~ dose, data=ToothGrowth) 
proto(environment(stats:::confint.lm), # set parent 
    vcov = function(x) hccm(x), #robust var-cov matrix 
    confint.lm = stats:::confint.lm)[["confint.lm"]](model) 

Per un altro esempio, vedi esempio 2 here.

2) ambienti.Il codice è un po 'più oneroso senza proto (infatti raddoppia approssimativamente il formato codice), ma qui è:

library(car) 

trace(hccm) 

model <- lm(len ~ dose, data=ToothGrowth) 
local({ 
    vcov <- function(x) hccm(x) #robust var-cov matrix 
    confint.lm <- stats:::confint.lm 
    environment(confint.lm) <- environment() 
    confint.lm(model) # confint will call vcov, but not the above one. 
}, envir = new.env(parent = environment(stats:::confint.lm))) 

EDIT: vari miglioramenti nella chiarezza

+0

Questo è geniale, non avevo familiarità con il pacchetto proto, ma mi sembra piuttosto utile. Ho continuato a leggere la vignetta, ed è una buona lettura. Grazie per aver fatto lo sforzo! – Stefan

2

Questo perché le funzioni confint e vcov sono nello spazio dei nomi "stats". La confint() che chiami qui ottiene effettivamente stats :: vcov, praticamente perché questo è lo scopo dei namespace - ti è permesso di scrivere le tue versioni delle cose ma non a discapito del comportamento altrimenti previsto.

Nel primo esempio, è comunque possibile chiamare in modo sicuro altre funzioni che si basano su stats :: lm e che non verranno sconvolte dalla modifica locale.

+0

OK, quindi tranne classe (modello) <- c ("lmr", classe (modello)); vcov.lmr <- function (x) hccm (x); confint (modello); non ci sono trucchi per indicare la funzione desiderata? (scusate il commento in linea) – Stefan

Problemi correlati