This question is related to this one.
Given a data.table and an expression, the function below creates a new column by reference for the expression result:
dat <- data.table(x = 1:4, y = 5:8)
new_column_1 <- function(df, col_name, expr) {
col_name <- deparse(substitute(col_name))
expr1 <- substitute(expr)
df[, (col_name) := eval(expr1
,df ,parent.frame() # THIS LINE CAN BE DROPPED
)]
}
new_column_1 (dat, z, x + y)
dat
x y z
<int> <int> <int>
1: 1 5 6
2: 2 6 8
3: 3 7 10
4: 4 8 12
However, if we insert the intermediary code for expr1
directly inside eval
, it does not work:
dat <- data.table(x = 1:4, y = 5:8)
new_column_2 <- function(df,col_name,expr){
col_name <- deparse(substitute(col_name))
df[, (col_name):=eval(substitute(expr) # expr1 code inserted here
,df ,parent.frame() # CAN NOT DROP THIS LINE
)]
}
new_column_2 (dat, z ,x + y)
dat
x y z
<int> <int> <call>
1: 1 5 eval(substitute(expr), df, parent.frame())
2: 2 6 eval(substitute(expr), df, parent.frame())
3: 3 7 eval(substitute(expr), df, parent.frame())
4: 4 8 eval(substitute(expr), df, parent.frame())
What is going on? I would expect the same result.
OBS: Notice that in the first case we can drop eval's arguments, but not in the second case because it causes an error.