2

I have a call object and I want to add an argument, and I don't want to use parse in the way this answer does.

So, say I have an lm object, and so the call from the lm

lma <- lm(mpg ~ cyl, data=mtcars)
lma$call
# lm(formula = mpg ~ cyl, data = mtcars)

now, say I wanted to add an argument, weights=wt, using the call. I realize that there is an incredibly easy way to just create a new call, but I'm wondering if I can work with a call object. there is also a way to edit weights if it were already in there

lmb <- lm(mpg ~ cyl, data=mtcars, wei=wt)
cl <- lmb$call
wtpos <- which.max(pmatch(names(cl), "weights"))
cl[[wtpos]] <- mtcars$qsec
eval(cl)

but this won't work on lma$call because there is no weights argument in lma$call.

so, it feels like I should be able to simply "grow" the call by adding another element, but I don't see how to do that. For example, the following fails:

cl <- lma$call
cl <- c(cl, weights=quote(wt))
eval(cl)
# [[1]]
# lm(formula = mpg ~ cyl, data = mtcars)
#
# $weights
# wt

so, I would hope for the result to be a new "lm" object equal to the lmb, not just a list.

While there is a workaround, that doesn't use parse (to modify a copy of lm to have wt=weights as the default similar to in this solution) that, again, doesn't involve editing the call object.

Community
  • 1
  • 1
pdb
  • 1,574
  • 12
  • 26

1 Answers1

4

I believe that the pryr package provides some useful functions for manipulating calls:

lma <- lm(mpg ~ cyl, data=mtcars)
lm_call <- lma$call

library(pryr)
modify_call(lm_call,list(weights = runif(32)))

> lm_call2 <- modify_call(lm_call,list(weights = runif(32)))
> eval(lm_call2)

Call:
lm(formula = mpg ~ cyl, data = mtcars, weights = c(0.934802365722135, 
0.983909613220021, 0.762353664264083, 0.23217184189707, 0.850970500381663, 
0.430563687346876, 0.962665138067678, 0.318865151610225, 0.697970792884007, 
0.389103061752394, 0.824285467388108, 0.676439745584503, 0.344414771301672, 
0.292265978176147, 0.925716639030725, 0.517001488478854, 0.726312294835225, 
0.842773627489805, 0.669753148220479, 0.618112818570808, 0.139365098671988, 
0.843711007386446, 0.851153723662719, 0.134744396666065, 0.92681276681833, 
0.00274682720191777, 0.732672147220001, 0.4184603120666, 0.0912447033915669, 
0.427389309043065, 0.721000595251098, 0.614837386412546))

Coefficients:
(Intercept)          cyl  
     38.508       -2.945  

You can look inside pryr::modify_call to see what it's doing if you'd like to do it manually, I suppose.

joran
  • 169,992
  • 32
  • 429
  • 468
  • 1
    Thanks for the tip. Searching for this lead to a much simpler solution in Wickham's Advanced R under Expressions:Calls:Modifying a call (online at http://adv-r.had.co.nz/Expressions.html#calls). `cl <- lma$call; cl$weights <- quote(wt); eval(cl)` gives me the result I want. – pdb Mar 03 '17 at 18:17