R: temporarily overriding functions and namespace / space

Consider the following R code:

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

This temporarily cancels the lm function, but after running local it will return to normal operation. I am wondering why the same approach does not work in the following following example:

 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. }) 

The confint function uses the vcov function to get standard errors for coefficients, and the idea is to use a robust var-cov matrix that temporarily overrides vcov without doing things β€œmanually” or changing functions.

Both vcov and confint are generic functions, I do not know if this is the reason that it is not working properly. This is not a concrete example that interests me as such; rather a conceptual lesson. Is this a namespace or a problem scope?

+6
source share
2 answers

We show how to do this using proxy objects (see the "Proxies" section of this document ), first using proto package , and then without:

1) proto . Because confint.lm calls vcov , we need to make sure that (a) our new replacement for vcov is in the revised confint.lm environment, and (b) the revised confint.lm can still access objects from the original. (For example, confint.lm calls the hidden function format.perc in statistics, so if we did not execute the second point to be true, then the hidden function cannot be accessed.)

To accomplish the above, we create a new confint.lm , which is the same, except that it has a new environment (proxy environment) that contains our vcov replacement and whose parent element, in turn, is the original confint.lm environment. Below, the proxy environment is implemented as a proto-object in which the key elements that you should know here are: (a) proto-objects are environments and (b) the placement of the function in the proto-object in such a way, as shown, changes its environment as a proto object. In addition, to avoid problems when sending S3 confint to confint.lm , we call the confint.lm method directly.

Although hccm does not seem to have a different result, we can verify that it was running by noticing the output of 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) 

In the following example, see example 2 here .

2) environment . The code is a bit more onerous without proto (actually it roughly doubles the size of the code), but here it is:

 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: various improvements in clarity

+4
source

This is because the confint and vcov are in the "stats" namespace. The conflict () that you call here gets statistics :: vcov effectively, largely because there are namespaces for that - you are allowed to write your own versions, but not to the detriment of the expected behavior.

In the first example, you can safely call other functions that depend on stats :: lm, and this will not be upset due to your local modification.

+2
source

Source: https://habr.com/ru/post/909054/


All Articles