0

Let's say I want to make a function which makes a sum of chosen fields within datatable. I.e., arguments for this function include: dtInput - datatable to be processed, fldID - column with unique row id, flds2Sum - vector of fields' names to be summed, fldsRes - name of the field to put result. Here is an example:

dt1 <- fread(
  "id,a,b,c,d
       id1,1,10,2,1
       id2,2,30,5,0
       id3,3,40,6,2
       id4,4,25,6,3
     ")

sumflds <- function(dtInput, fldID, flds2Sum, fldsRes) {
  dtInput[, fldsRes:={
    as.character(sum(mget(flds2Sum))) # this doesn't work correctly
  }, by=fldID, with=FALSE]
  return(dtInput);
}

dt2 <- sumflds(dt1, "id", c("c","a","d"), "res")

As I use with=FALSE, such references as fldID and fldsRes are processed correctly. But inside :={} block, I can't address values in desired way. I would be grateful for any advices.

vrajs5
  • 4,066
  • 1
  • 27
  • 44
Vasily A
  • 8,256
  • 10
  • 42
  • 76
  • I assume using `get` will reference the column properly. – Blue Magister May 29 '14 at 02:27
  • possible duplicate of [Variably selecting/assigning to fields in a data.table](http://stackoverflow.com/questions/12391950/variably-selecting-assigning-to-fields-in-a-data-table) – Blue Magister May 29 '14 at 02:27
  • thanks for pointing out! However, simple introducing `get` (I changed the code in question) didn't solve the problem: now there's no error thrown, but result is wrong: instead of sum of three columns, I get only first of three... – Vasily A May 29 '14 at 02:41

1 Answers1

1

get is not vectorized, so you could use mget instead. Note that you will need to use do.call(sum,...). Note I have explicitly copied the input dataset, otherwise the original dt1 is altered by reference. I have also forced the evaluation of fldsRes by using ()

In this case, I think it easier to use .SD and .SDcols, eg

sumflds <- function(dtInput, fldID, flds2Sum, fldsRes) {
   copy(dtInput)[,(fldsRes) := do.call(sum,.SD), by = fldID, .SDcols = flds2Sum]
}

dt2 <- sumflds(dt1, "id", c("c","a","d"), "res")
dt2
#       id a  b c d res
# 1:   id1 1 10 2 1   4
# 2:   id2 2 30 5 0   7
# 3:   id3 3 40 6 2  11
# 4:   id4 4 25 6 3  13
mnel
  • 113,303
  • 27
  • 265
  • 254