2012-02-22 14 views
6

Consideremos el siguiente código R:R: Las funciones primordiales temporal y el alcance/espacio de nombres

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

Esto anula temporalmente la función lm, pero una vez que se ha ejecutado local va a "volver a la normalidad". Me pregunto por qué no parece trabajar en el siguiente ejemplo sencillo el mismo enfoque:

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 función confint utiliza la función vcov para obtener los errores estándar de los coeficientes, y la idea es utilizar una robusta Var- matriz cov anulando temporalmente vcov, sin hacer cosas "manualmente" o alterando funciones.

Tanto vcov como confint son funciones genéricas, no sé si esta es la razón por la que no funciona según lo previsto. No es el ejemplo específico que me interesa como tal; más bien la lección conceptual. ¿Es este un espacio de nombres o un "problema" de alcance?

Respuesta

4

Nos muestran cómo hacer esto utilizando objetos proxy (ver sección La representación de esta document), primero utilizando la proto package y luego sin:

1) proto. Dado que confint.lm llama al vcov, debemos asegurarnos de que (a) nuestro nuevo reemplazo para vcov esté en el entorno revisado confint.lm y (b) el confint.lm revisado todavía pueda acceder a los objetos desde su original. (Por ejemplo, confint.lm llama a la función oculta format.perc en las Estadísticas por lo que si no nos organizamos para el segundo punto de ser cierto que la función oculta No se tiene acceso.)

Para realizar lo anterior se crea un nuevo confint.lm que es el mismo, excepto que tiene un nuevo entorno (el entorno de proxy) que contiene nuestra sustitución vcov y cuyo padre a su vez es el entorno original confint.lm. A continuación, el entorno de proxy se implementa como un objeto proto donde los elementos clave que debe conocer son: (a) protoobjetos son entornos y (b) colocar una función en un protoobjeto de la manera que se muestra cambia su entorno para que sea ese objeto proto . También para evitar cualquier problema del envío S3 de confint a confint.lm llamamos directamente al método confint.lm.

Aunque el hccm no parecen tener ningún resultado diferente aquí podemos comprobar que fue ejecutado, si percibe la salida 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) 

Para otro ejemplo, véase el ejemplo 2 here.

2) entornos.El código es un poco más oneroso y sin proto (de hecho, casi duplica el tamaño del código), pero aquí está:

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: diversas mejoras en la claridad

+0

Eso es brillante, no estaba familiarizado con el paquete de proto pero me parece bastante útil. Seguí leyendo la viñeta, y es una buena lectura. Gracias por hacer el esfuerzo! – Stefan

2

Esto se debe a que las funciones confint y vcov están ambas en el espacio de nombres "stats". El confint() que llama aquí de manera efectiva obtiene stats :: vcov, más o menos porque para eso están los espacios de nombres: puede escribir sus propias versiones de las cosas pero no en detrimento del comportamiento esperado.

En su primer ejemplo, todavía puede llamar de manera segura a otras funciones que dependen de stats :: lm y que no se alterarán con la modificación local.

+0

OK, por lo que a excepción de clase (modelo) <- c ("lmr", clase (modelo)); vcov.lmr <- function (x) hccm (x); confint (modelo); no hay trucos para señalar la función deseada? (perdón por el comentario en línea) – Stefan

Cuestiones relacionadas