1

In miceadds::lm.cluster() the call is represented in this manner stats::lm(formula = formula, data = data) and I want to replace it with the actual formula.

For example, there is the function call stored inside an lm() object

fit <- lm(Sepal.Length ~ Petal.Length, iris)
> fit$call
lm(formula = Sepal.Length ~ Petal.Length, data = iris)

I'm attempting to change it with call() with no success so far.

fit$call <- call("lm(formula = Sepal.Length ~ Petal.Length, data = iris, foo = NULL)")
> fit$call
`lm(formula = Sepal.Length ~ Petal.Length, data = iris, foo = NULL)`()

There are these `` and the () at the end. class() yields call, though, but it's still not the same as just lm(formula = Sepal.Length ~ Petal.Length, data = iris, foo = NULL).

I also tried formula() and reformulate() but failed.

How can I do this?

jay.sf
  • 60,139
  • 8
  • 53
  • 110

2 Answers2

2

This will do it, but we're all still curious why...

The problem you're having is that call doesn't take a full function call like you're giving it; instead, just give it the name of the function as the first parameter, and then the parameters you want to use, quoting anything you don't want evaluated.

> fit$call <- call("lm", Sepal.Length ~ Petal.Length, 
                   data=quote("iris"), foo=NULL)
> fit

Call:
lm(Sepal.Length ~ Petal.Length, data = "iris", foo = NULL)

Coefficients:
 (Intercept)  Petal.Length  
      4.3066        0.4089  

This is what miceadds probably should be doing, though with do.call to actually execute it; if it were, it would be recording the call as you want. See https://stackoverflow.com/a/17026386/210673 for one example.

You might be able to make your own function that calls lm.cluster and does what you want, see below for an example. After looking into it, it would be tricky to fix lm.cluster, at least for the data piece, the formula piece would be an easy fix. For data it's harder to handle because the function could get passed an expression rather than the name of an object.

lm.special <- function(formula, data, ... ) {
  lm(formula=formula, data=data, ...)
}

lm.special2 <- function(formula, data.name) {
  cl <- call("lm.special", formula=formula, data=as.name(data.name))
  out <- eval(cl)
  out$call <- cl
  out
}

> lm(Sepal.Length ~ Petal.Length, iris)

Call:
lm(formula = Sepal.Length ~ Petal.Length, data = iris)

Coefficients:
 (Intercept)  Petal.Length  
      4.3066        0.4089  

> lm.special(Sepal.Length ~ Petal.Length, iris)

Call:
lm(formula = formula, data = data)

Coefficients:
 (Intercept)  Petal.Length  
      4.3066        0.4089  

> lm.special2(Sepal.Length ~ Petal.Length, "iris")

Call:
lm.special(formula = Sepal.Length ~ Petal.Length, data = iris)

Coefficients:
 (Intercept)  Petal.Length  
      4.3066        0.4089  
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
  • Works, thanks, even with `miceadds`! Though I couldn't solve the underlying problem with `miceadds` I learned a lot about `call()` today. – jay.sf Jul 10 '18 at 19:11
2

If you just want to replace a particular component, e.g. the formula:

fit$call$formula <- quote(foo ~ bar)

If you want to generate foo ~ bar programmatically rather than hard-coding it in your script, things get uglier ...

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453