majom
majom

Reputation: 8021

Data.table and get() command (R)

I have a problem including a data.table operation in a function. Input arguments are the data.table name and the column/variable name.

I can refer to the data.table by using the get() command. However, using the same command for the variable name doesn't work out. I know that get() might not be appropriate in case of the column/variable name, but I am stuck with which command to use.

EDITED: I have now included substitute() instead of get() and it still doesn't work.

toy_example_fun <- function(d, .expr){

  .expr = substitute(.expr)

  setkey(get(d), .expr)  # ==> doesn't work

  d.agg <- get(d)[,list(sum(y), sum(v)), by=.expr]  # --> works
}

toy_example_fun("DT", x)

ALTERNATIVE: quote() --> This works. However, I am interested in a solution that works inside a function.

DT <- data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9)    
d <- "DT"
variable <- quote(x)
d.agg <- get(d)[,list(sum(y), sum(v)), by=variable]  

Even though, the latter alternative works variable <- quote(x) produces an error message:

  <simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'x' not found>
    <simpleError in is.scalar(val): object 'x' not found>
    <simpleError in is.data.frame(obj): object 'x' not found> 

Thanks for your help.

Upvotes: 3

Views: 477

Answers (1)

Andrie
Andrie

Reputation: 179428

Here you go:

someFun <- function(d, .expr){
  group <- substitute(.expr)
  get(d)[,list(sum(y), sum(v)), by=group]
}

someFun("DT", x)
   group V1 V2
1:     a 10  6
2:     b 10 15
3:     c 10 24


someFun("DT", "x")
   x V1 V2
1: a 10  6
2: b 10 15
3: c 10 24

EDIT from Matthew :

+1 to above. And/Or character column names are acceptable to by directly, too :

someFun = function(d, col) {
    get(d)[,list(sum(y),sum(v)),by=col]
}
someFun("DT","x")
   x V1 V2
1: a 10  6
2: b 10 15
3: c 10 24
someFun("DT","x,y")
   x y V1 V2
1: a 1  1  1
2: a 3  3  2
3: a 6  6  3
4: b 1  1  4
5: b 3  3  5
6: b 6  6  6
7: c 1  1  7
8: c 3  3  8
9: c 6  6  9

but then someFun("DT",x) won't work. So Adrie's answer is more general.


EDIT with setkeyv

someFun <- function(d, cols){
  setkeyv(get(d), cols)
  cols <- substitute(cols)
  get(d)[,list(sum(y), sum(v)), by=cols]
}

someFun("DT", "x")
   x V1 V2
1: a 10  6
2: b 10 15
3: c 10 24

Upvotes: 3

Related Questions