[Rd] match.arg

Spencer Graves spencer.graves@pdf.com
Mon Feb 24 17:56:05 2003

Thanks for your reply.

I'm trying to generalize the MASS function "stepAIC" to study the 
effects of hierarchy for both interactions and parabolic terms.  I 
include a new argument 'hierarchy = c("include", "exclude", "ignore")' 
being a 2-vector, with the first component for interaction and the 
second for parabolic terms:

	* "exclude" fails to consider A:B (or A^2) unless both A and B are 
currently in the model.  This is the current default for interactions 
but not for parabolic terms.

	* "include" forces A:B to be evaluated with 3 degrees of freedom if 
neither A nor B are currently in the model, 2 degrees of freedom if only 
1 are in the model, and 1 degree of freedom if both are currently in the 
model (assuming A and B are both either numerical variables or 2-level 
factors).  George Box says he invented response surface methods for a 
chemical plant that had only interactions.  The plan had gone through 
several general managers, who had done what they could with one factor 
at a time experiments.  I plan to analyze several Taguchi 3-level 
experiments in order to evaluate effect sparcity and the frequency with 
which both interactions and parabolic terms occur in industrial 
experimentation, and I need an automated way of doing this.

	* "ignore" means include or exclude the interaction independent of 
whether the main effect is in the model.  This is the current default 
for A^2.

I want to make "include" the default for both A:B and A^2.  In my 
revision of stepAIC, I call match.arg as follows;

	 hierarchy <- rep(match.arg(hierarchy), length=2)

What do you think?  I know that one example does not justify adding a 
rarely used option to a general tool.  However, it occurred to me that 
there might be other applications


Thanks for reminding me about the "seq(length= length(arg))" 
construction.  After I sent that email, I discovered that problem, and 
added the following line right before the "for" loop:

	if((length(arg)==length(choices)) && all(arg==choices))

Since I had heard no reply, I decided not to issue a "correction" to an 
email that might go nowhere or might only irritate the recipients.

Thanks again for your comments and all your effort and creativity in the 
R project.

Best Wishes,
Spencer Graves

Martin Maechler wrote:
>>>>>>"Spencer" == Spencer Graves <spencer.graves@pdf.com>
>>>>>>    on Mon, 17 Feb 2003 17:43:23 -0800 writes:
>     Spencer> Hello: I'm not on the "r-devel" list, but I just
>     Spencer> modified "match.arg" from R 1.6.2 for Windows to
>     Spencer> accept a vector for "arg".
>     Spencer> 	  Is it appropriate that I send such things to
>     Spencer> this email address for consideration for inclusion
>     Spencer> in a future release?
> yes (using "R-devel" for ...). 
> But why is this current proposal really useful?
> Note that I can't see reason to match more than one argument to the
> *same* list of choices. `choices' already is a vector typically...
> Making a function more complicated makes it also more
> error-prone, so I think we'd need a good motivation for it.
> E.g., your proposal below quite badly fails when
> length(arg) == 0, since you've used the ``well-known to be unsafe''
> 1:length(arg) idiom instead of the safe  seq(length= length(arg)) one.
> Regards,
> Martin
>     Spencer> 	  I just compared this with "match.arg" in
>     Spencer> S-Plus 6.1 for Windows.  There, I got the
>     Spencer> following:
>     >> match.arg(c("a","b"), c("aa", "bb"))
>     Spencer> [1] "aa" "bb"
>     Spencer> 	  However, match.arg(c("a", "b")) in a test
>     Spencer> function with "default" = c("aa", "bb") returned
>     Spencer> only "a"; the following returns c("aa", "bb").
>     Spencer> Thanks for all your hard work in developing this
>     Spencer> marvelous product.
>     Spencer> Sincerely, Spencer Graves
>     match.arg <-
>     function (arg, choices)
>     {
> 	 if (missing(choices)) {
> 	     formal.args <- formals(sys.function(sys.parent()))
> 	     choices <- eval(formal.args[[deparse(substitute(arg))]])
> 	 }
>     #	 cat("choices =", choices, "\n")
> 	     for(j in 1:length(arg)){
> 		if (all(arg[j] == choices))
> 		 arg[j] <- choices[1]
> 		     else{
> 			i <- pmatch(arg[j], choices)
> 		     if (is.na(i))
> 		      stop(paste("ARG should be one of", paste(choices, collapse = 
>     ", "),
> 			       sep = " "))
> 			if (length(i) > 1)
> 			 stop("there is more than one match in match.arg")
> 		     arg[j] <- choices[i]
> 		    }
> 	    }
> 	    arg
>     }