Multiply two subsets to a data.table inline

50 views Asked by At

I am trying to accomplish the following

library(data.table)

DT <- data.table(
  ID=c("b", "b", "b", "a", "a", "c"), 
  a=1:6, 
  b=7:12, 
  c=13:18
)

I am trying to accomplish the following

oldcols <- c("a", "b")
newcols <- c("a_1", "b_1")
DT[, c(..newcols) := DT[, ..ldcols]*1e-2*DT[, "c"]]

this is not working. what am I doing wrong?

2

There are 2 answers

0
B. Christian Kamgang On

One way to solve your problem. Note that you can use a data.frame (and therefore .SD) followed by a multiplication operator (*). In the following example, each column in .SD will be multiplied by 1e-2 * c.

DT[, (newcols) := .SD * 1e-2 * c, .SDcols=oldcols]

       ID     a     b     c   a_1   b_1
   <char> <int> <int> <int> <num> <num>
1:      b     1     7    13  0.13  0.91
2:      b     2     8    14  0.28  1.12
3:      b     3     9    15  0.45  1.35
4:      a     4    10    16  0.64  1.60
5:      a     5    11    17  0.85  1.87
6:      c     6    12    18  1.08  2.16
0
anearlytuesday On

In data.table, the LHS of the := operator must be a character vector. Since you want to use a character vector that is bound to a name in the global environment, you have to enclose the name in (). The RHS of the := operator must be a list, e.g, the return value of lapply().

DT[, (newcols) := lapply(.SD, \(x) x * 1e-2 * c), .SDcols = oldcols]

lapply() applies the anonymous function \(x) x * 1e-2 * c to each element of .SD, which is defined as oldcols in the .SDcols argument. Note this anonymous function could have also been written as function(x) x * 1e-2 * c.