2

I'm having trouble transitioning to data.table. I am trying to group by some categorical variables, and apply a list of functions that each target different variables in order to create new columns. This is something that seems like it should be easy with mapply or Map, but I can't figure out to assemble the proper subset in the to pass to the functions.

Here is what it looks like,

set.seed(2015)
dat <- data.table(cat1 = factor('Total'),
                  cat2 = factor(rep(letters[1:4], 5)),
                  cat3 = factor(rep(1:4, each=5)),
                  var1 = sample(20),
                  var2 = sample(20),
                  var3 = sample(20))

## I have list of factor columns to group by
groups <- c(paste0("cat", 1:3))
setkeyv(dat, groups)

## List of functions, and corresponding list of column names that
## they are to be applied to.  So, in this example I should get
## two new columns: V1=sum(var1) and V2=mean(var2, var3)
thing <- function(...) mean(c(...), na.rm=TRUE)  # arbitrary function
funs <- list("sum", "thing")                     # named functions
targets <- list("var1", c("var2", "var3"))       # variables
outnames <- funs                                 # names or result columns

## Can't get this part
f <- function(fn, vars) do.call(fn, vars)
dat[, outnames := Map(f, funs, targets), by=groups]

The result for this example should be like this

dat[, `:=`(sum=sum(var1), thing=thing(var2, var3)), by=groups]

1 Answer 1

3

We need to subset the dataset columns based on the column names in the 'targets' list. One way would to loop through the list elements of 'targets' and subset the data.table (.SD[, x, with=FALSE]), and then apply the function.

dat[, unlist(outnames) := Map(f, funs, lapply(targets, function(x)
                          .SD[, ..x])), by = groups]
Sign up to request clarification or add additional context in comments.

1 Comment

great, looks good, I might have a follow up question in a bit, since I also need to be subsetting by indices at the same time. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.