I have the following data.table
:
> dt = data.table(expr = c("a + b", "a - b", "a * b", "a / b"), a = c(1,2,3,4), b = c(5,6,7,8))
> dt
expr a b
1: a + b 1 5
2: a - b 2 6
3: a * b 3 7
4: a / b 4 8
My aim is to get the following data.table
:
> dt
expr a b ans
1: a + b 1 5 6
2: a - b 2 6 -4
3: a * b 3 7 21
4: a / b 4 8 0.5
I tried the following:
> dt[, ans := eval(expr)]
Error in eval(expr, envir, enclos) : object 'expr' not found
> dt[, ans := eval(parse(text = expr))]
Error in parse(text = expr) : object 'expr' not found
Any idea how can I calculate the ans
column based on the expression in the expr
column?
Return value The eval() function returns the result of evaluating the object.
data.table is an R package that provides an enhanced version of data.frame s, which are the standard data structure for storing data in base R. In the Data section above, we already created a data.table using fread() . We can also create one using the data.table() function.
Data tables contain data in a tabular form (it is the equivalent of two-dimensional arrays in programming). A data table contains rows and columns and each item stored in the data table can be retrieved through its unique row and column number.
If your actual expressions describe calls to vectorized functions and are repeated many times each, this may be more efficient, since it only parses and evaluates each distinct expression one time:
f <- function(e, .SD) eval(parse(text=e[1]), envir=.SD)
dt[, ans:=f(expr,.SD), by=expr, .SDcols=c("a", "b")]
# expr a b ans
# 1: a + b 1 5 6.0
# 2: a - b 2 6 -4.0
# 3: a * b 3 7 21.0
# 4: a / b 4 8 0.5
Really, there are a bunch of challenges for vectorization in such a setup. eval
doesn't expect to run on a vector of expressions nor is it set up to iterate over a vector of environments by default. Here I define a helper function to wrap much of the iteration
calc <- function(e, ...) {
run<-function(x, ...) {
eval(parse(text=x), list(...))
}
do.call("mapply", c(list(run, e), list(...)))
}
dt[, ans:=calc(expr,a=a,b=b)]
which returns
expr a b ans
1: a + b 1 5 6.0
2: a - b 2 6 -4.0
3: a * b 3 7 21.0
4: a / b 4 8 0.5
as desired. Note that you'll need to name the parameters in the call to calc()
so it knows which column to map to which variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With