User2321
User2321

Reputation: 3062

How to subtract numeric element from list element in data table

I have the following data table:

dat = data.table(j = c(3,8,9,11,10,28), gr = c(9,9,9,9,10,10),
                     res = list(3, c(3,8), c(3,8,9), c(3,8,9,11),
                                10, c(10, 28)))
> dat
    j gr         res
1:  3  9           3
2:  8  9         3,8
3:  9  9       3,8,9
4: 11  9  3, 8, 9,11
5: 10 10          10
6: 28 10       10,28

The res column is a list that contains numeric vectors and what I would like to achieve is to subtract from each vector of res the corresponding numeric value of j.

I tried the following:

dat[, new_res := sapply(res, function(x) x - j)

But this does not work as it subtracts the whole vector j every time, while I want only the row value to be subtracted. My ideal result would be:

res_dat = data.table(j = c(3,8,9,11,10,28), gr = c(9,9,9,9,10,10),
                         res = list(3, c(3,8), c(3,8,9), c(3,8,9,11),
                                    10, c(10, 28)), new_res = list(0, c(-5, 0), c(-6,-1,0), c(-8, -3, -2, 0), 0, c(-18, 0)))
> res_dat
    j gr         res     new_res
1:  3  9           3           0
2:  8  9         3,8       -5, 0
3:  9  9       3,8,9    -6,-1, 0
4: 11  9  3, 8, 9,11 -8,-3,-2, 0
5: 10 10          10           0
6: 28 10       10,28     -18,  0

Why doesn't the subtraction work at the row level as usually in data.table?

Upvotes: 1

Views: 153

Answers (2)

akrun
akrun

Reputation: 887038

Using map2 from purrr

library(data.table)
library(purrr)
dat[, new_res := map2(res, j, `-`)]

-ouptut

> dat
    j gr         res     new_res
1:  3  9           3           0
2:  8  9         3,8       -5, 0
3:  9  9       3,8,9    -6,-1, 0
4: 11  9  3, 8, 9,11 -8,-3,-2, 0
5: 10 10          10           0
6: 28 10       10,28     -18,  0

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388862

You need to pass both res and j in parallel so use Map.

library(data.table)

dat[, new_res := Map(`-`, res, j)]
dat

#    j gr         res     new_res
#1:  3  9           3           0
#2:  8  9         3,8       -5, 0
#3:  9  9       3,8,9    -6,-1, 0
#4: 11  9  3, 8, 9,11 -8,-3,-2, 0
#5: 10 10          10           0
#6: 28 10       10,28     -18,  0

Upvotes: 2

Related Questions