1

I have the following function:

DT <- data.table(col1 = 1:4, col2 = c(2:5))

fun <- function(DT, fct){
  DT_out <- DT[,new_col := fct]
  return(DT_out)
}

fun(input, fct = function(x = col1, y = col2){y - x})

In reality I have some processing before and after this code snippet, thus I do not wish to use directly the statement DT[,new_col := fct] with a fixed fct (because the fct should be flexible). I know this question is very similar to this one, but I cannot figure out how to reformulate the code such that two columns as arguments for the function are allowed. The code above gives the error:

Error in `[.data.table`(DT, , `:=`(new_col, fct)) : 
  RHS of assignment is not NULL, not an an atomic vector (see ?is.atomic) and not a list column. 
2
  • 1
    Do you want new_col := fct(col1,col2)? As it is, you're assigning a function to new_col, not it's output Commented Mar 20, 2020 at 16:28
  • No that won't satisfy my needs, because I want the arguments to be flexible like in the answer given below! But thanks anyway Commented Mar 20, 2020 at 18:54

1 Answer 1

3

One option if you don't mind adding quotes around the variable names

fun <- function(DT, fun, ...){
  fun_args <- c(...)
  DT[,new_col := do.call(fun, setNames(mget(fun_args), names(fun_args)))]
}

fun(DT, fun = function(x, y){y - x}, x = 'col1', y = 'col2')

DT
#    col1 col2 new_col
# 1:    1    2       1
# 2:    2    3       1
# 3:    3    4       1
# 4:    4    5       1

Or use .SDcols (same result as above)

fun <- function(DT, fun, ...){
  fun_args <- c(...)
  DT[, new_col := do.call(fun, setNames(.SD, names(fun_args))), 
     .SDcols = fun_args]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yesss! Both are nice solutions, but I like the second one with .SDcols better. It is clearer and more in the style of data.table in my opinion. And thanks a lot for pointing out the three-dots construct, this opens a whole new world for me!

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.