0

Unqualified data tables, passed as function arguments, are modifiable without copy on modify:

dt<-data.table(RowId=c('a','b','c','d'),x=0:3)
f<-function(adt){adt[,x:=4]}
f(dt)
dt
#   RowId x
#1:     a 4
#2:     b 4
#3:     c 4
#4:     d 4

I'd like to preserve this behavior on a restricted set of rows as in:

f(dt[x>1])
dt
#   RowId x
#1:     a 0
#2:     b 1
#3:     c 4
#4:     d 4

rather than having to embed the restriction in the function or passing the restriction as an argument to be evaled within the function.

Is there a way to accomplish this?

If not, what is the most parsimonious way of replacing the rows of dt corresponding to those in the copy returned from the function?

user3673
  • 665
  • 5
  • 21

2 Answers2

0

As far as I know you cannot.

but you can do

myfun <-function (x){
    4
}

dt[x>1,x:=myfun(x)]
DJJ
  • 2,481
  • 2
  • 28
  • 53
  • Why would it be any more dangerous than the first case, which is currently permitted? – user3673 May 20 '17 at 20:44
  • What if the `function` modifies, or even initializes, more than one column? – user3673 May 20 '17 at 20:45
  • You are right it's not more dangerous than the first case. If you want a function that modifies more than one column Have a look [here](http://stackoverflow.com/questions/11308754/add-multiple-columns-to-r-data-table-in-one-function-call#11308946) – DJJ May 20 '17 at 20:52
  • That looks like it's getting there with the expression `DT[, c("new1","new2") := myfun(y,v)]`, however that relies on knowing the order of the returned columns rather than on their names. – user3673 May 20 '17 at 22:18
  • Granted but I think you can control the return order in the `myfun` – DJJ May 20 '17 at 22:28
  • 1
    How about this: `dt[f(dt[x>1]),x:=i.x,on="RowId"]` ? – user3673 May 22 '17 at 13:27
  • Sorry for the delay. I didn't know this specification. You should post it as an answer :-). – DJJ May 25 '17 at 20:49
0

This is what I ended up doing:

dt[f(dt[x>1]),x:=i.x,on="RowId"]

user3673
  • 665
  • 5
  • 21