在R的data.table中评估表达式

10

我有以下的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

我的目标是获得以下的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

我尝试了以下方法:

> 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

你知道如何根据“expr”列中的表达式计算“ans”列吗?

2个回答

14
如果您的实际表达式描述了对向量化函数的调用,并且每个表达式都重复多次,这可能更有效率,因为它仅解析和评估每个不同的表达式一次:

如果您的实际表达式描述了对向量化函数的调用,并且每个表达式都重复多次,这可能更有效率,因为它仅解析和评估每个不同的表达式一次:

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

8

在这种设置中,向量化存在许多挑战。 eval 不希望在表达式向量上运行,也没有默认情况下遍历环境向量的设置。在这里,我定义了一个辅助函数来包装大部分迭代操作。

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)]

该函数返回

    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

按照需要进行操作。请注意,您需要在调用calc()时命名参数,以便知道将哪一列映射到哪个变量。


函数式编程非常棒,大加赞赏。 - Colonel Beauvel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接