Loop through columns in a data.table and transform those columns

A workaround which I unfortunately discovered after I posted the question is as follows:

DT[, .SD, .SDcols = patterns('_')] - DT[, RF]

This also works in a more complicated setting in which there are additional columns you want to keep, but with some extra effort:

library(data.table)
DT <- data.table(RF  = 1:10,
                 S_1 = 11:20,
                 S_2 = 21:30,
                 addCol = rnorm(10)) #Column that should not be subtracted by RF, but still kept in DT

DT <- cbind(DT[, .SD, .SDcols = patterns("_")] - DT[, RF], addCol = DT[, addCol])

You were on the right track with your second attempt. Here is an approach that uses substitute to build the expression that gets passed in as the 'j' argument in DT[ , j ].

for (i in grep("_", names(DT), value=TRUE)){
    e <- substitute(X := X - RF, list(X = as.symbol(i)))
    DT[ , eval(e)]
}
DT
#     RF S_1 S_2
# [1,]  1  10  20
# [2,]  2  10  20
# [3,]  3  10  20
# [4,]  4  10  20
# [5,]  5  10  20

You could also use an LHS expression rather than a symbol :

for (i in grep("_", names(DT), value=TRUE))
    DT[, (i) := get(i)-RF]

Tags:

R

Data.Table