On Mon, 2 Nov 2009, Thushyanthan Baskaran wrote:
> Hi,
>
> I am trying to write a function to compute many cross-tabulations with the
> -svytable- command. Here is a simplified example of the structure of my
code
> (adapted from the -svytable- help file):
In the 'survey' package -- if you say what package you are using, people
don't have to guess.
>
> data(api)
> func.example<-function(variable){ dclus1<-svydesign(id=~1,
> weights=~pw,data=apiclus1, fpc=~fpc)
>
> svytable(~ variable, dclus1)
>
> }
> When I call this function with:
>
> func.example(api99)
>
> I get the following error:
>
>
> Error in eval(expr, envir, enclos) : object 'variable' not found.
Yes, that's because you don't have a variable called 'variable'
in the design object.
> (Everything works fine when I type svytable(~ api99, dclus1).)
>
> I guess that the problem has something to do with function environments
Not really. It has to do with how formulas are evaluated. To get substitution
into a formula you need to use substitute() or bquote(). You also need to stop
the argument being evaluated before it gets to the svytable() call, and this
sort of non-standard evaluation is not recommended unless you really need it.
The easiest solution is to pass a formula, not a variable
f.example1 <- function(formula){
dclus1<-svydesign(id=~1, weights=~pw,data=apiclus1, fpc=~fpc)
svytable(formula, dclus1)
}
f.example1(~comp.imp)
The next easiest way is to pass a character string
f.example2 <- function(varname){
dclus1<-svydesign(id=~1, weights=~pw,data=apiclus1, fpc=~fpc)
formula<-make.formula(varname)
svytable(formula, dclus1)
}
f.example2("comp.imp")
The next easiest way is to pass a quoted symbol
f.example3 <- function(variable){
dclus1<-svydesign(id=~1, weights=~pw,data=apiclus1, fpc=~fpc)
eval(bquote(svytable(~.(variable), dclus1)))
}
f.example3(quote(comp.imp))
and a really ugly solution is to use non-standard evaluation to avoid the
quote()
f.example4 <- function(variable){
v<-substitute(variable)
dclus1<-svydesign(id=~1, weights=~pw,data=apiclus1, fpc=~fpc)
eval(bquote(svytable(~.(v), dclus1)))
}
f.example4(comp.imp)
There's a good reason why the survey packages uses the first style, not the
last one. Occasionally, as with subset() or with(), you need to supply
arbitrary expressions and evaluate them somewhere else than the default
location, but this sort of thing really should be avoided if there is any
alternative. It's just too hard to extend and maintain.
-thomas
Thomas Lumley Assoc. Professor, Biostatistics
tlumley at u.washington.edu University of Washington, Seattle