3

I have this:

dt = data.table(index=c(1,2), items=list(c(1,2,3),c(4,5)))
#   index items
#1:     1 1,2,3
#2:     2   4,5

I want to change the dt[index==2,items] to c(6,7).

I tried:

dt[index==2, items] = c(6,7)
dt[index==2, items := c(6,7)]
pomber
  • 23,132
  • 10
  • 81
  • 94

3 Answers3

5

One workaround is to use ifelse:

 dt[,items:=ifelse(index==2,list(c(6,7)),items)]

   index items
1:     1 1,2,3
2:     2   6,7

EDIT the correct answer:

 dt[index==2,items :=  list(list(c(6,7)))]

Indeed, you'll need one more list because data.table uses list(.) to look for values to assign to columns by reference.


There are two ways to use the := operator in data.table:

  1. The LHS := RHS form:

    DT[, c("col1", "col2", ..) := list(val1, val2, ...)]
    

    It takes a list() argument on the RHS. To add a list column, you'll need to wrap with another list (as illustrated above).

  2. The functional form:

    DT[, `:=`(col1 = val1, ## some comments
              col2 = val2, ## some more comments
              ...)]
    

    It is especially useful to add some comments along with the assignment.

Arun
  • 116,683
  • 26
  • 284
  • 387
agstudy
  • 119,832
  • 17
  • 199
  • 261
2
dt[index==2]$items[[1]] <- list(c(6,7))
dt
#    index items
# 1:     1 1,2,3
# 2:     2   6,7

The problem is that, the way you have it set up, dt$items is a list, not a vector, so you have to use list indexing (e.g., dt$items[[1]]). But AFAIK you can't update a list element by reference, so, e.g.,

dt[index==2,items[[1]]:=list(c(6,7))] 

will not work.

BTW I also do not see the point of using data.tables for this.

jlhoward
  • 58,004
  • 7
  • 97
  • 140
  • This column is part of a bigger data.table, I'm using it mainly because of the binary search. – pomber Dec 26 '14 at 21:57
0

This worked:

dt$items[[which(dt$index==2)]] = c(6,7)
pomber
  • 23,132
  • 10
  • 81
  • 94