Reputation: 578
Suppose there is a data.table as under:
exp <- structure(list(
id = c("a", "b"),
num1 = c(1L, 5L),
num2 = list(c(2L, 5L, 8L),
c(6L, 10L, 13L, 19L))),
.Names = c("id", "num1", "num2"),
row.names = c(NA, -2L),
class = c("data.table", "data.frame"))
See the data.table:
exp
id num1 num2
1: a 1 2,5,8
2: b 5 6,10,13,19
Also see the structure:
str(exp)
Classes ‘data.table’ and 'data.frame': 2 obs. of 3 variables:
$ id : chr "a" "b"
$ num1: int 1 5
$ num2:List of 2
..$ : int 2 5 8
..$ : int 6 10 13 19
My problem is how to create an additional column (say, diff) which will show the difference between num1 (integer) and num2 (list containing integers) columns. For the first row it should show 1, 4, 7 and for second row it should show 1, 5, 8, 14.
The following code obviously does not work:
exp[, `:=`(diff = num1 - num2)]
Neither does
exp[, `:=`(diff = num1 - unlist(num2))]
Any help will be appreciated.
Upvotes: 2
Views: 130
Reputation: 7630
Your question simplifies to a question about subtracting lists from a vector:
num1 <- c(1L, 5L)
num2 <- list(c(2L, 5L, 8L),
c(6L, 10L, 13L, 19L))
# Method A: these are both defined
num1[[1]] - num2[[1]]
num1[[2]] - num2[[2]]
# Method B: this is not:
num1 - num2
# This is how you programatically do Method A:
mapply(`-`, num1, num2)
Just put the mapply call in your data table subset expression.
Upvotes: 2
Reputation: 70336
This can be done using Map
:
exp[, diff := Map("-", num2, num1)]
exp
# id num1 num2 diff
#1: a 1 2,5,8 1,4,7
#2: b 5 6,10,13,19 1, 5, 8,14
The num1-values are recycled to the length of the num2 list-element and then subtracted. Map
always returns a list-result.
Upvotes: 3