1
votes

I'm using Firth and Turner's BradleyTerry2 package for paired comparisons but have run into a mysterious problem using the main fitting function BTm. Here is a minimal data setup from their own example:

data(citations, package = "BradleyTerry2")
citations.sf <- countsToBinomial(citations)
names(citations.sf)[1:2] <- c("journal1", "journal2")

So at the console the following works:

citeModel <- BTm(cbind(win1, win2), journal1, journal2, data = citations.sf)

but the following does not work

f1 <- function(x){ BTm(cbind(win1, win2), journal1, journal2, data=x) }
f1(citations.sf)

while this (statistically nonsensical but) structurally similar linear model example does work, just as I would expect:

f2 <- function(x){ lm(log(win1/win2) ~ journal1, data=x) }
f2(citations.sf)

The error with f1 is "Error in eval(substitute(expr), data, enclos = parent.frame()): invalid 'envir' argument". But this is not telling me anything I can understand.

Thoughts?

1
Have you tried traceback() or debugging with options(error=recover)? - Ari B. Friedman
When you do use traceback() and look at the code of both BTm and lm you see that BTm uses the function with whereas lm does not. The use of with inside functions is not advised because of exactly the mismatching of environment difficulties being reported. - IRTFM
@AriB.Friedman I had used traceback, but didn't (don't) know enough about scope in R to make use of the information. Now reading github.com/hadley/devtools/wiki/Environments again in the hope of enlightenment. - conjugateprior
@DWin OK, I figured there was something unusual about the implementation. I've not had this happen before. - conjugateprior
I wouldn't say it's necessarily just the use of with that's the problem. I have found it surprisingly hard to build modeling packages in R that use data arguments and evaluate them correctly in all possible circumstances ... - Ben Bolker

1 Answers

2
votes

Thanks for linking to this post on the existing bug report [#2294] objects not found when BTm not called in global environment.

When setting up the data internally, BTm looks for objects in the environment of the formula and then in the global environment. If a formula is not specified to BTm, then the formula is defined internally and, as currently implemented, inherits the environment constructed when BTm is called, rather than the environment from which BTm was called.

Until I get round to fixing this, there is a simple work-around - always specify a formula when using BTm inside a function, so that the environment of the formula is that created when your function is called. E.g.

> f1 <- function(x){ BTm(cbind(win1, win2), journal1, journal2, ~.., data=x) }
> f1(citations.sf)
Bradley Terry model fit by glm.fit 

Call:  BTm(outcome = cbind(win1, win2), player1 = journal1, player2 = journal2, 
    formula = ~.., data = x)

Coefficients:
..Comm Statist          ..JASA        ..JRSS-B  
       -2.9491         -0.4796          0.2690  

Degrees of Freedom: 6 Total (i.e. Null);  3 Residual
Null Deviance:  1925 
Residual Deviance: 4.293    AIC: 46.39