Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to use eval(parse(...)) in data.table [,:=] function

Tags:

r

data.table

I am not sure if I made an error here (dangers of using eval(parse(...))perhaps), but here I tried to use eval(parse(...)) while updating a data.table column, which creates an error. Below is my code.

require(data.table)
# Loading required package: data.table
# data.table 1.9.2  For help type: help("data.table")
DT<-data.table(x=seq(1,10,1),
               y=seq(2,20,2))
DT[,y:=y*eval(parse(text="1*2"))] #Doesn't work
# Error in y * expression(1 * 2) : non-numeric argument to binary operator
variable <- eval(parse(text="1*2"))
DT[,y:=y*variable] #Works
DT
#     x  y
# 1:  1  4
# 2:  2  8
# 3:  3 12
# 4:  4 16
# 5:  5 20
# 6:  6 24
# 7:  7 28
# 8:  8 32
# 9:  9 36
#10: 10 40
like image 958
Wet Feet Avatar asked Mar 13 '14 10:03

Wet Feet


1 Answers

This behaviour, bug #5423, is now fixed in commit #1234 in the current development version of data.table v1.9.3. From NEWS:

o DT[,y := y * eval(parse(text="1*2"))] resulted in error unless eval() is wrapped with paranthesis. That is, DT[,y := y * (eval(parse(text="1*2")))]. Now fixed, closes #5423. Thanks to Wet Feet for reporting and to Simon O'Hanlon for identifying the issue here on SO.


Regardless of why you want to do this and the relative merits or not, this is about order of precedence. You need to wrap the whole eval(parse(text="1*2")) in a set of parentheses to ensure that it is evaluated before you try to multiply it by y...

DT[,y:=y*(eval(parse(text="1*2")))] 
#     x  y
# 1:  1  4
# 2:  2  8
# 3:  3 12
# 4:  4 16
# 5:  5 20
# 6:  6 24
# 7:  7 28
# 8:  8 32
# 9:  9 36
#10: 10 40

Without the parentheses data.table::":=" is trying to multiply y by an expression object, which will result in a syntax error.

like image 139
Simon O'Hanlon Avatar answered Sep 28 '22 05:09

Simon O'Hanlon