简体   繁体   中英

Pass generic column names to xtabs function in R

Is there any way to pass generic column names to functions like xtabs in R?

Typically, I'm trying to do something like:

xtabs(weight ~ col, data=dframe)

with col and weight two columns of my data.frame , weight being a column containing weights. It works, but if I want to wrap xtabs in a function to which I pass the column names as argument, it fails. So, if I do:

xtabs.wrapper <- function(dframe, colname, weightname) {
    return(xtabs(weightname ~ colname, data=dframe))
}

it fails. Is there a simple way to do something similar? Perhaps I'm missing something with R logic, but it seems to me quite annoying not to be able to pass generic variables to such functions since I'm not particularly fond of copy/paste.

Any help or comments appreciated!

Edit: as mentioned in comments, I was suggested to use eval and I came with this solution:

xtabs.wrapper <- function(dframe, wname, cname) {
    xt <- eval(parse(text=paste("xtabs(", wname, "~", cname, ", data=",
                         deparse(substitute(dframe)), ")")))
    return(xt)
}

As I said, I seems to me to be an ugly trick, but I'm probably missing something about the language logic.

Not sure if this is any prettier, but here is a way to define a function without using eval ... it involves accessing the correct columns of dframe via [] :

    xtabs.wrapper <- function(dframe, wname, cname) {
      tmp.wt <- dframe[,wname]
      tmp.col <- dframe[,cname]
      xt <- xtabs(tmp.wt~tmp.col)
      return(xt)
    }

Or you can shorten the guts of the function to:

    xtabs.wrapper2 <- function(dframe, wname, cname) {
      xt <- xtabs(dframe[,wname]~dframe[,cname])
      return(xt)
    }

To show they are equivalent here with an example from the mtcars data:

    data(mtcars)
    xtabs(wt~cyl, mtcars)
    xtabs.wrapper(mtcars, "wt", "cyl")
    xtabs.wrapper2(mtcars, "wt", "cyl")

I did this once:

    creatextab<-function(factorsToUse, data)
    {      
            newform<-as.formula(paste("Freq ~", paste(factorsToUse, collapse="+"), sep=""))
           xtabs(formula= newform, drop.unused.levels = TRUE, data=data)  
}

Obviously this is a different form because of the Freq, but basically .. you can generate the forumula as a string and then you are just using xtabs() directly.

If you want an n-way crosstab and cname contains a string of variable names, then you'll want the following:

xtabs.wrapper3 <- function(dframe, wname, cname) {
  eval(cname)
  formula <- paste0(wname, " ~ ", paste0(cname, collapse=" + ") )
  xt <- xtabs(formula, data = dframe)
  return(xt)
}

xtabs.wrapper3(mtcars, "wt", c("cyl", "vs"))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM