我有一个data.table和一个公式列表,
DT <- data.table(A = c(1:3), B = c(3:1), C = c(4:6), D = (6:4))
l <- list(f1 = "A + B", f2 = "B + C", f3 = "C - D", f4 = "D / A")
这可以通过
来实现DT[, ":="(f1 = A + B, f2 = B + C, f3 = C - D, f4 = D / A)]
或
for (i in 1:length(l)) {
DT[, eval(names(l)[i]) := eval(parse(text=l[[i]]))]
}
有没有办法在不使用循环的情况下使用l
中的信息执行此操作?
# some code
DT
# A B C D f1 f2 f3 f4
# 1: 1 3 4 6 4 7 -2 6.000000
# 2: 2 2 5 5 4 7 0 2.500000
# 3: 3 1 6 4 4 7 2 1.333333
答案 0 :(得分:10)
如果您手动构建l
,请将其写为
L = quote(`:=`(f1 = A + B, f2 = B + C, f3 = C - D, f4 = D / A))
然后你可以像
一样使用它DT[, eval(L)]
# A B C D f1 f2 f3 f4
# 1: 1 3 4 6 4 7 -2 6.000000
# 2: 2 2 5 5 4 7 0 2.500000
# 3: 3 1 6 4 4 7 2 1.333333
这是recommended practice from the FAQ,它解释了......
quote()
和eval()
就像其他语言中的宏一样。
答案 1 :(得分:2)
这非常草率,但您可以使用call
,parse
和paste
创建表达式,然后调用该表达式:
library(data.table)
DT <- data.table(A = c(1:3), B = c(3:1), C = c(4:6), D = (6:4))
l <- list(f1 = "A + B", f2 = "B + C", f3 = "C - D", f4 = "D / A")
ncall <- call(":=", names(l),
parse(text = paste0("list(", paste(l, collapse = ","), ")")))
DT[ , eval(ncall)]
DT
# A B C D f1 f2 f3 f4
# 1: 1 3 4 6 4 7 -2 6.00000000
# 2: 2 2 5 5 4 7 0 2.50000000
# 3: 3 1 6 4 4 7 2 1.33333333