[R] dots expansion

Gabor Grothendieck ggrothendieck at myway.com
Wed Aug 4 16:14:41 CEST 2004

Viet Nguyen <vietnguyen <at> fastmail.fm> writes:

> Thanks to all who helped.
> I used your ideas and code samples to write the following (for the 
> benefit of people who will search this list later):
> rbind.case <- function(..., name="case", values) {
>     dots <- list(...);
>     if (missing(values)) values <- 1:length(dots);
>     if (length(values)!=length(dots))
>       stop("length(values)!=length(list(...))");
>     eval(parse(text=
>                paste("cbind(rbind(...), ",name,
>                      "=rep(values, sapply(dots, nrow)))",sep="")));
> }
> The function is to be used with data frames. It's not as good as it can 
> be but it works for my purpose.

Regarding improvements, eliminate the semicolons at the end of statements,
place the default value for values= in the arg list to make it more readable,
use stopifnot to check args (also for readability), add a check for 
data frames (which is mentioned after the code but not checked for, 
and eliminate the eval and rep calculations by simply lapplying over an 
index and appending the name column to each data frame in turn:

rbind.case <- function(..., name="case", values = seq(along = list(...))) 
# rbind the ... data frames together adding a column named name whose 
# value for rows from ith argument is values[i]
   dots <- list(...)
   stopifnot(length(dots) == length(values),
	   all(sapply(dots, inherits, "data.frame")))

   f <- function(i) { x <- dots[[i]]; x[,name] <- values[i]; x }
   do.call("rbind", lapply(seq(along = dots), f))

More information about the R-help mailing list