Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make lm display in its output a formula passed to it as a variable

Tags:

r

Please consider the following example code (from the lm doc):

ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14)
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69)
group <- gl(2,10,20, labels=c("Ctl","Trt"))
weight <- c(ctl, trt)
lm(weight ~ group)
form1 <- weight ~ group
lm(form1)
do.call("lm",list(formula=form1))

With the following (abbreviated) output:

> lm(weight ~ group)

Call:
lm(formula = weight ~ group)

> lm(form1)

Call:
lm(formula = form1)

> do.call("lm",list(formula=form1))

Call:
lm(formula = weight ~ group)

As you can see, the second call to lm does not display the formula, but the variable containing the formula. With some experimenting, I came up with the third solution, but I find that one a bit tedious.

The question hence is: is there another way to make lm display the formula instead of the variable (i.e. without using the do.call method I used above).

(The reason I want this is that I am working on a Sweave document, so I cannot see the calls, only the outputs, and then is having lm tell you what formula it used very handy.)


EVEN BETTER SOLUTION - Thanks to @Aaron

lm <- function(...) {
  mf <- match.call()
  mf[[1]] <- quote(stats::lm)
  env <- parent.frame()
  mf$formula <- eval(mf$formula, env)
  eval(mf, env)
}

SOLUTION: Based on G. Grothendieck's answer, I came up with the following function:

lm <- function(...) {
    mf <- match.call()
    mf[[1]] <- quote(stats::lm)
    env <- parent.frame()
    fm <- eval(mf, env)
    fm$call$formula <- formula(fm)
    fm
}
like image 492
ROLO Avatar asked Dec 16 '22 02:12

ROLO


2 Answers

Put this near the top of your Sweave file:

<<preliminaries,echo=FALSE,results=hide>>=
lm <- function(fo, ...) { fm <- stats::lm(fo, ...); fm$call <- fo; fm }
@

and then call lm normally in the rest of the file.

Using the example in the question and assuming we have defined lm as above:

> lm(form1)

Call:
weight ~ group

Coefficients:
(Intercept)     groupTrt  
      5.032       -0.371  
like image 177
G. Grothendieck Avatar answered Jan 31 '23 00:01

G. Grothendieck


This might be just as tedious, but at least it contains fewer characters ;)

R> eval(call("lm",form1))

Call:
lm(formula = weight ~ group)

Coefficients:
(Intercept)     groupTrt  
      5.032       -0.371 
like image 24
BenBarnes Avatar answered Jan 31 '23 00:01

BenBarnes