R data.table - dividing columns in character vector by columns in another character vector

Viewed 31

I want to divide the columns in one character vector by the columns in another character vector in a data.table. Easiest to explain with an example:

dt <- data.table(g1 = c('a', 'b', 'a', 'b'),
                 x1 = rep(1:2, 2),
                 x2 = 10:13)    
dt2 <- dt[dt[x1==1], on = c('g1')]
dt2
   g1 x1 x2 i.x1 i.x2
1:  a  1 10    1   10
2:  a  1 12    1   10
3:  a  1 10    1   12
4:  a  1 12    1   12

Now I want to create two new columns: x1_n = x1 / i.x1 and x2_n = x2 / i.x2. My actual data has many more columns so it's too cumbersome to write out and may change. I'm trying:

cc <- c('x1', 'x2')
icc <- paste0('i.', cc)
new_c <- paste0(cc, '_n')
dt2[, (new_c) := mget(cc) / mget(icc)]
Error in mget(cc)/mget(icc) : non-numeric argument to binary operator

I'm not sure how that final step should be written. I feel like I'm missing something simple. Thanks friends.

1 Answers

You're close, I think just you need Map:

nms1 <- grep("^x[0-9]", names(dt2), value = TRUE)
nms2 <- paste0("i.", nms1)
nmsn <- paste0(nms1, "_n")

nms1
# [1] "x1" "x2"
nms2
# [1] "i.x1" "i.x2"
nmsn
# [1] "x1_n" "x2_n"
dt2[, c(nmsn) := Map(`/`, mget(nms1), mget(nms2))]
dt2
#        g1    x1    x2  i.x1  i.x2  x1_n      x2_n
#    <char> <int> <int> <int> <int> <num>     <num>
# 1:      a     1    10     1    10     1 1.0000000
# 2:      a     1    12     1    10     1 1.2000000
# 3:      a     1    10     1    12     1 0.8333333
# 4:      a     1    12     1    12     1 1.0000000

The use of `/` (backtick-escaped) is the way in R to call in infix operator as a function. An equivalent way to write that:

dt2[, c(nmsn) := Map(function(a, b) a / b, mget(nms1), mget(nms2))]
Related