Reputation: 3062
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
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
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