sfcheung
sfcheung

Reputation: 468

In R, How to let update() find a variable created inside the function calling update()?

I want to call update() to re-fit a model inside a function. I want to keep the variable to be added inside the function. However, update() usually works by evaluating the call in the environment returned by parent.frame(). How can I insert the local variable in the search such that update can find it?

This works if done in the console:

set.seed(8700)
x <- rnorm(10)
y <- rnorm(10)
z_global <- rnorm(10)
lm_out <- lm(y ~ x)
update(lm_out, . ~ . + z_global)

The output is:


Call:
lm(formula = y ~ x + z_global)

Coefficients:
(Intercept)            x     z_global  
    0.08648      0.49040      0.18212  

However, this is what I want to do:

set.seed(8700)
x <- rnorm(10)
y <- rnorm(10)
lm_out <- lm(y ~ x)
tmpfct <- function(fit) {
    z_local <- rnorm(10)
    update(fit, . ~ . + z_local)
  }
tmpfct(lm_out)

It does not work:

Error in eval(predvars, data, env) : object 'z_local' not found

I guess it is because update() evaluates the call of fit in parent.frame(), which is the calling environment of tmpfct(lm_out), that is, the global environment. z_local is not defined there.

I tried to insert an environment in the function, hoping that the parent.frame() in update() will be the execution environment of this function. However, this also does not work:

set.seed(8700)
x <- rnorm(10)
y <- rnorm(10)
lm_out <- lm(y ~ x)
tmpfct <- function(fit) {
    z_local <- rnorm(10)
    tmp_env <- new.env(environment())
    eval(update(fit, . ~ . + z_local), envir = tmp_env)
  }
tmpfct(lm_out)

The error message is the same:

Error in eval(predvars, data, env) : object 'z_local' not found

How should I modify the code such that when evaluating the call, update() can find z_local created inside the function?

Upvotes: 1

Views: 127

Answers (1)

TarJae
TarJae

Reputation: 78927

Update: OP's request:

Without using z_local as second argument:

set.seed(8700)
x <- rnorm(10)
y <- rnorm(10)
lm_out <- lm(y ~ x)
tmpfct <- function(fit) {
    update(fit, . ~ . + rnorm(10))
}
tmpfct(lm_out)

First answer: You miss the second argument z_local:

set.seed(8700)
x <- rnorm(10)
y <- rnorm(10)
lm_out <- lm(y ~ x)
tmpfct <- function(fit, z_local) {
    z_local <- rnorm(10)
    update(fit, . ~ . + z_local)
}
tmpfct(lm_out)

Output:

Call:
lm(formula = y ~ x + z_local)

Coefficients:
(Intercept)            x      z_local  
    0.08648      0.49040      0.18212  

Upvotes: 2

Related Questions