San
San

Reputation: 578

Difference between an integer column and integer values in a list column

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

Answers (2)

De Novo
De Novo

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

talat
talat

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

Related Questions