-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1
[Sorry to those who don't like it for top-posting]
Thierry, I'm curious whether this addresses your problem (although
we don't have a hard timetable for the next release [it has to avoid
conflicts with the 3.2.0 release in 2.5 weeks at the very least], so
this might be problematic if your package needs to depend on it).
I'm still curious whether there are any ideas/opinions from other
readers. Has anyone else struggled with this? Is there a canonical
solution?
Ben Bolker
On 15-03-24 07:55 PM, Ben Bolker wrote:
> On 15-03-23 12:55 PM, Thierry Onkelinx wrote:
>> Dear Ben,
>
>> Last week I was struggling with incorporating lme4 into a
>> package. I traced the problem and made a reproducible example (
>> https://github.com/ThierryO/testlme4). It looks very simular to
>> the problem you describe.
>
>> The 'tests' directory contains the reproducible examples.
>> confint() of a model as returned by a function fails. It even
>> fails when I try to calculate the confint() inside the same
>> function as the glmer() call (see the fit_model_ci function).
>
>> Best regards,
>
>> Thierry
>
>
> Ugh. I can get this to work if I also try searching up the call
> stack, as follows (within update.merMod). This feels like "code
> smell" to me though -- i.e., if I have to hack this hard I must be
> doing something wrong/misunderstanding how the problem *should* be
> done.
>
>
> if (evaluate) { ff <- environment(formula(object)) pf <-
> parent.frame() ## save parent frame in case we need it sf <-
> sys.frames()[[1]] tryCatch(eval(call, env=ff), error=function(e) {
> tryCatch(eval(call, env=sf), error=function(e) { eval(call, pf) })
> }) } else call
>
> Here is an adapted even-more-minimal version of your code, which
> seems to work with the version of update.merMod I just pushed to
> github, but fails for glm():
>
>
> ##
> https://github.com/ThierryO/testlme4/blob/master/R/fit_model_ci.R
> fit_model_ci <- function(formula, dataset, mfun=glmer){ model <-
> mfun( formula = formula, data = dataset, family = "poisson" ) ci <-
> confint(model) return(list(model = model, confint = ci)) }
>
> library("lme4") set.seed(101) dd <-
> data.frame(f=factor(rep(1:10,each=100)), y=rpois(2,1000))
> fit_model_ci(y~(1|f),dataset=dd)
> fit_model_ci(y~(1|f),dataset=dd,mfun=glm)
>
>
>
>
>
>> ir. Thierry Onkelinx Instituut voor natuur- en bosonderzoek /
>> Research Institute for Nature and Forest team Biometrie &
>> Kwaliteitszorg / team Biometrics & Quality Assurance
>> Kliniekstraat 25 1070 Anderlecht Belgium
>
>> To call in the statistician after the experiment is done may be
>> no more than asking him to perform a post-mortem examination: he
>> may be able to say what the experiment died of. ~ Sir Ronald
>> Aylmer Fisher The plural of anecdote is not data. ~ Roger Brinner
>> The combination of some data and an aching desire for an answer
>> does not ensure that a reasonable answer can be extracted from a
>> given body of data. ~ John Tukey
>
>> 2015-03-22 17:45 GMT+01:00 Ben Bolker :
>
>> WARNING: this is long. Sorry I couldn't find a way to compress
>> it.
>
>> Is there a reasonable way to design an update method so that it's
>> robust to a variety of reasonable use cases of generating calls
>> or data inside or outside a function? Is it even possible?
>> Should I just tell users "don't do that"?
>
>> * `update.default()` uses `eval(call, parent.frame())`; this
>> fails when the call depends on objects that were defined in a
>> different environment (e.g., when the data are generated and the
>> model initially fitted within a function scope)
>
>> * an alternative is to store the original environment in which
>> the fitting is done in the environment of the formula and use
>> `eval(call, env=environment(formula(object)))`; this fails if the
>> user tries to update the model originally fitted outside a
>> function with data modified within a function ...
>
>> * I think I've got a hack that works below, which first tries in
>> the environment of the formula and falls back to the parent
>> frame if that fails, but I wonder if I'm missing something much
>> simpler ..
>
>> Thoughts? My understanding of environments and frames is still,
>> after all these years, not what it should be ...
>
>> I've thought of some other workarounds, none entirely
>> satisfactory:
>
>> * force evaluation of all elements in the original call *
>> printing components of the call can get ugly (can save the
>> original call before evaluating) * large objects in the call get
>> duplicated * don't use `eval(call)` for updates; instead try to
>> store everything internally * this works OK but has the same
>> drawback of potentially storing large extra copies * we could try
>> to use the model frame (which is stored already), but there are
>> issues with this (the basis of a whole separate rant) because the
>> model frame stores something in between predictor varia