Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calling lmer from within a package that Suggests: or Imports: #50

Closed
bbolker opened this issue Jun 27, 2013 · 11 comments
Closed

calling lmer from within a package that Suggests: or Imports: #50

bbolker opened this issue Jun 27, 2013 · 11 comments

Comments

@bbolker
Copy link
Member

bbolker commented Jun 27, 2013

Several packages (aod, EquiNorm) call lmer from within package functions, but they only Suggest: (aod) or Import: (EquiNorm) lme4. This leads to an error when we use eval(mc, parent.frame(1L)) to pass the arguments off to lFormula: R can't find lFormula in the parent frame -- presumably (although I don't understand this as well as I'd like to) lFormula can be found when called from the context of package functions, but not when called from the global environment.

In fact, we can get the same thing simply by calling

data(sleepstudy,package="lme4")
lme4::lmer(Reaction~Days+(1|Subject),sleepstudy)
Error in eval(expr, envir, enclos) : could not find function "lFormula"

without loading lme4 first.

A reasonable workaround is to make the package Depend: on lme4 ... although it shouldn't have to.

@stevencarlislewalker
Copy link
Member

Could another workaround be to add lme4:::lFormula in lmer? And likewise for other similar problems?

@bbolker
Copy link
Member Author

bbolker commented Jun 27, 2013

Maybe, but that feels like a hack. We should (ideally) figure out how this is supposed to work rather than cluttering up our code with lme4::: ...

@stevencarlislewalker
Copy link
Member

Agreed.

@mmaechler
Copy link
Member

Ben Bolker notifications@github.com
on Thu, 27 Jun 2013 09:34:17 -0700 writes:

> Maybe, but that feels like a hack.  We should (ideally) figure out how this is *supposed* to work rather than cluttering up our code with `lme4:::` ...
> ---

Agreed.... if it worked at all.
That would be a hack clearly indicating that we are doing
something "the wrong way".

As I think this is all linked to the non-standard
evaluation of formulas, we should solve this by ensuring that
the environment of our formulas is correct...
[but then I have not recently looked the code we are talking about..]

Martin

@bbolker
Copy link
Member Author

bbolker commented Jun 27, 2013

It's (for once) not actually very deeply buried. The relevant code is just:

mc <- mcout <- match.call()
## snip
mc[[1]] <- as.name("lFormula")
lmod <- eval(mc, parent.frame(1L))  ## parse data and formula

So this is a fairly standard trick -- e.g. just the same as what lm() uses to construct the model.frame. It occurred to me to try setting the enclosing environment, but I don't know if that's just making things more complicated than they need to be ...

@mmaechler
Copy link
Member

hOn Thu, Jun 27, 2013 at 7:34 PM, Ben Bolker notifications@github.comwrote:

It's (for once) not actually very deeply buried. The relevant code is
just:

mc <- mcout <- match.call()

snip

mc[[1]] <- as.name("lFormula")
lmod <- eval(mc, parent.frame(1L)) ## parse data and formula

So this is a fairly standard trick -- e.g. just the same as what lm() uses
to construct the model.frame.

indeed..... and I now checked:

R_DEFAULT_PACKAGES=NULL R --vanilla

.... and try a simple lm() using

stats::lm(....)

you also get an error, about function "model.frame" not found.

So we could ask R-core if this is not a "bug" to be fixed...
and actually... contrary to what i said earlier ... we could argue that
when R can live with this bug / "infelicity",
lme4 could do so, as well.

Martin

It occurred to me to try setting the enclosing environment, but I don't
know if that's just making things more complicated than they need to be ...


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-20141594
.

@yihui
Copy link

yihui commented Jun 28, 2013

I think you can use do.call:

mc = match.call()
do.call(lFormula, as.list(mc[-1]), envir = parent.frame(1))

The key is to let R know the symbol lFormula when the package is complied. If you use as.name('lFormula'), R will not recognize lFormula as a symbol; by the time it is called by other packages, it is too late for R to be aware of it. That is my understanding.

I just tested this between two packages, and this trick worked.

@JoshOBrien
Copy link

Along the lines of Yihui's suggestion, how about just:

mc[[1]] <- lFormula
lmod <- eval(mc, parent.frame(1L))

@bbolker
Copy link
Member Author

bbolker commented Jun 28, 2013

Duncan Murdoch also suggests mc[[1]] <- lFormula (or using lme4::lFormula) at http://article.gmane.org/gmane.comp.lang.r.devel/33814 , but points out that this will make any error messages ugly unless we use call.=FALSE in all subsequent stop() messages. This is a particular pain in the butt because [g]lFormula are argument-checking functions, so there will be lots of stop() calls to modify. That suggests that Yihui's solution might be best?

@JoshOBrien
Copy link

No, Yihui's solution will also make the error messages ugly. That's because, like my proposed code, it works by substituting the value of lFormula for its symbol before the call to it gets evaluated.

Duncan Murdoch's second suggestion, on the other hand, -- doing mc[[1]] <- quote(lme4::lFormula) -- has the virtue of not uglifying error messages triggered by the call to lFormula. His seems to me like the cleanest solution ... even if it somehow doesn't feel like you should have to use the :: construct in this way.

bbolker added a commit that referenced this issue Jun 28, 2013
bbolker added a commit that referenced this issue Jun 28, 2013
bbolker added a commit that referenced this issue Jun 28, 2013
@bbolker
Copy link
Member Author

bbolker commented Jun 28, 2013

OK, I gave up and used :: . Seems to work OK. Thanks to all for commentary.

@bbolker bbolker closed this as completed Jun 28, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants