[R] invalid variable type in model.frame within a function

Thomas Lumley tlumley at u.washington.edu
Fri Mar 24 18:24:32 CET 2006


On Fri, 24 Mar 2006, Ingmar Visser wrote:

>
>> On Thu, 23 Mar 2006, Ingmar Visser wrote:
>>
>>> Dear expeRts,
>>>
>>> I came across the following error in using model.frame:
>>>
>>> # make a data.frame
>>> jet=data.frame(y=rnorm(10),x1=rnorm(10),x2=rnorm(10),rvar=rnorm(10))
>>> # spec of formula
>>> mf1=y~x1+x2
>>> # make the model.frame
>>> mf=model.frame(formula=mf1,data=jet,weights=rvar)
>>>
>>> Which gives the desired output:
>> <output snipped>
>>> However, doing this inside another function like this:
>>>
>>> makemodelframe <- function(formula,data,weights) {
>>>    mf=model.frame(formula=formula,data=data,weights=weights)
>>>    mf
>>> }
>>>
>>> produces the following error:
>>>
>>>> makemodelframe(mf1,jet,weights=rvar)
>>> Error in model.frame(formula, rownames, variables, varnames, extras,
>>> extranames,  :
>>>    invalid variable type
>>>
>>>
>>> Searching the R-help archives I came across bug-reports about this but
>>> couldn't figure out whehter the bug was solved or whether there are
>>> work-arounds available.
>>

<snippage>
>>
>> I don't think it's a good idea for people to write code like this. I
>> should admit (especially since it's Lent at the moment, and so is an
>> appropriate time to repent one's past errors) that I lobbied Ross and
>> Robert to make model.frame() work compatibly with S-PLUS in its treatment
>> of weights= arguments (when porting the survival package, nearly ten
>> years ago).  They were reluctant at the time, and I now think they were
>> right, although this level of S-PLUS compatibility might have been
>> unavoidable.
>>
>> I would advise writing your code so that you the call looks like
>>    makemodelframe(mf1,jet,weights=~rvar)
>> That is, pass all the variables that are going to be evaluated in the
>> data= argument as formulas (or as quoted expressions).  This is basically
>> what lme() does, where you supply two formulas and then various other bits
>> and pieces as objects. It is what my survey package does.
>>
>> Then a user can do
>>    makemodelframe(mf1,jet,weights=rvar)
>> if rvar is a variable in the current environment and
>>    makemodelframe(mf1,jet,weights=~rvar)
>> if rvar is a variable in the data= argument, and both will work.
>
> I'm still getting the same error using:
>
>> jet=data.frame(y=rnorm(10),x1=rnorm(10),x2=rnorm(10),rvar=rnorm(10))
>> # spec of formula
>> mf1=y~x1+x2
>>
>> makemodelframe <- function(formula,data,weights) {
> +     mf=model.frame(formula=formula,data=data,weights=weights)
> +     mf
> + }
>>
>> makemodelframe(mf1,jet,weights=jet$rvar)
> Error in model.frame(formula, rownames, variables, varnames, extras,
> extranames,  :
>    invalid variable type
>> makemodelframe(mf1,jet,weights=~rvar)
> Error in model.frame(formula, rownames, variables, varnames, extras,
> extranames,  :
>    invalid variable type

Well, yes.

Your function makemodelframe isn't going to work with any set of 
arguments.
    model.frame(formula=formula,data=data,weights=weights)
uses 'weights' without evaluating it as the name of a local variable or a 
column in the data= argument. There's no way this can refer to jet$rvar.

You need to rewrite your code.  The options for rewriting it are to make 
it do the same trickery that model.frame does (which is explained on 
developer.r-project.org) or to make it take a formula for weights (which 
is *also* explained on developer.r-project.org, under "non-standard 
evaluation").  I was advising the latter approach.


 	-thomas




More information about the R-help mailing list