1

I have data similar to this:

set.seed(1)
testing1 <- data.table(type=c("stock","stock","bond","bond"),a=rnorm(4),b=rnorm(4),c=rnorm(4),d=rnorm(4),e=rnorm(4))

    type          a          b          c           d           e
1: stock -0.6264538  0.3295078  0.5757814 -0.62124058 -0.01619026
2: stock  0.1836433 -0.8204684 -0.3053884 -2.21469989  0.94383621
3:  bond -0.8356286  0.4874291  1.5117812  1.12493092  0.82122120
4:  bond  1.5952808  0.7383247  0.3898432 -0.04493361  0.59390132

This returns exactly what I want:

result1 <- testing1[,c(list(type=type),lapply(.SD, `-`, a)), .SDcols = b:e]

    type          b          c           d          e
1: stock  0.9559616  1.2022352  0.00521323  0.6102635
2: stock -1.0041117 -0.4890317 -2.39834321  0.7601929
3:  bond  1.3230577  2.3474098  1.96055953  1.6568498
4:  bond -0.8569561 -1.2054376 -1.64021441 -1.0013795

The problem is that the column a is dynamically named. I would like to do something like this:

cn <- "a"
result2 <- testing1[,c(list(type=type), lapply(.SD, `-`, get(cn))), .SDcols = b:e]

but I get the error message: Error in FUN(X[[i]], ...) : non-numeric argument to binary operator.

Any ideas would be greatly appreciated. Thanks.

FG7
  • 469
  • 4
  • 14

1 Answers1

1

We can make use of [[ to extract the column from 'testing1'. Here .SD would not work as the column is not specified in .SDcols

testing1[,c(list(type=type),lapply(.SD, `-`, testing1[[cn]])), .SDcols = b:e]
#   type          b          c           d          e
#1: stock  0.9559616  1.2022352  0.00521323  0.6102635
#2: stock -1.0041117 -0.4890317 -2.39834321  0.7601929
#3:  bond  1.3230577  2.3474098  1.96055953  1.6568498
#4:  bond -0.8569561 -1.2054376 -1.64021441 -1.0013795

If we are using get, make sure the environment is the same as with lapply, the environment is from .SD which doesn't have the column 'a'. Instead use Map

testing1[,  Map(`-`, .SD, list(get(cn))), .SDcols = b:e]
akrun
  • 874,273
  • 37
  • 540
  • 662