Bug 15892 - nlme:anova unable to find formula object defined inside function
Summary: nlme:anova unable to find formula object defined inside function
Status: NEW
Alias: None
Product: R
Classification: Unclassified
Component: Add-ons (show other bugs)
Version: R 3.0.2
Hardware: x86_64/x64/amd64 (64-bit) Windows 64-bit
: P5 major
Assignee: R-core
Depends on:
Reported: 2014-07-20 10:17 UTC by sandeep.pulla
Modified: 2014-09-07 23:12 UTC (History)
3 users (show)

See Also:

Code that reproduces the bug (476 bytes, text/plain)
2014-07-20 10:17 UTC, sandeep.pulla

Note You need to log in before you can comment on or make changes to this bug.
Description sandeep.pulla 2014-07-20 10:17:07 UTC
Created attachment 1628 [details]
Code that reproduces the bug

anova.gls() does not use the appropriate frame while looking for the formula object. The attached code demonstrates the problem, which results in the following stack trace at the first does.not.work() call:

Error in eval(expr, envir, enclos) : object 'form' not found
16: eval(expr, envir, enclos)
15: eval(x$call$model)
14: formula.gls(object)
13: formula(object)
12: getResponseFormula(el)
11: deparse(getResponseFormula(el)[[2]])
10: FUN(X[[1L]], ...)
9: lapply(object, function(el) deparse(getResponseFormula(el)[[2]]))
8: unlist(lapply(object, function(el) deparse(getResponseFormula(el)[[2]])))
7: nlme::anova.lme(object = m1, m2)
6: eval(expr, envir, enclos)
5: eval(expr, p)
4: eval.parent(Call)
3: anova.gls(m1, m2)
2: anova(m1, m2) at #5
1: does.not.work(dat)


platform       x86_64-w64-mingw32          
arch           x86_64                      
os             mingw32                     
system         x86_64, mingw32             
major          3                           
minor          0.2                         
year           2013                        
month          09                          
day            25                          
svn rev        63987                       
language       R                           
version.string R version 3.0.2 (2013-09-25)
nickname       Frisbee Sailing 

Comment 1 sandeep.pulla 2014-07-23 10:30:58 UTC
The more general problem seems to be that objects in 'nlme' store (and evaluate) a reference to the formula object used at the time of their creation, rather than a copy of it. Apart from the problem of searching for (and using) formula objects from the wrong environment, it creates a potentially dangerous situation if the object being referred to gets modified subsequently. Subsequent attempts to evaluate the formula (say, update.gls()) will refer to the modified object rather than the original formula. The solution is to store/evaluate a copy of the formula.
Comment 2 Ben Bolker 2014-09-02 03:14:02 UTC
I would say this is generally difficult. I know that I have spent a *lot* of time trying to get the equivalent functionality in `lme4` to work reliably (I just tested, and the equivalent construction in `lme4` *does* work); we mainly achieve that by making sure that everything we need is stored in the environment of the formula.
Comment 3 sandeep.pulla 2014-09-07 17:41:09 UTC
Can the formula object could be evaluated prior to being stored in gls (etc.) objects?

form = a ~ b
gls(form, data)

gls = function(...) {
  fn.call = match.call()
  fn.call[[2]] # "form"
  eval(fn.call[[2]]) # "a ~ b"
Comment 4 Duncan Murdoch 2014-09-07 23:12:41 UTC
I think your analysis is not quite correct:  the formula object isn't a reference, it looks as though nlme is working with a copy of the call, so it is just a name "form" which it re-evaluates as necessary.  That looks like a bug.  
As you say, it should evaluate argument "model" when gls(model=...) is called.

Since nlme is a recommended package, not a base package, I can't fix it.  But if you submit a patch that fixes it and it looks reasonable, I'll try to get it incorporated.