通过字符串访问 data.table 字段的函数;或者,如何在 lm 中模仿 data=

Accessing functions of data.table fields via strings; or, how to imitate data= in lm

我正在尝试构建一个从 data.table 字段派生的变量矩阵;

为了具体起见,假设我有一个带有变量 x1x2x3 的 data.table dt,我想使 nrow(dt)x4 矩阵,列为 x1log(x1)as.numeric(as.factor(x3))3*x2-x1.

一个一次性的解决方案是调用

cbind(dt$x1, log(dt$x1), as.numeric(as.factor(data$x3)), 3 * data$x2-data$x1)

但我想要一些更具延展性的东西——稍后我会用这个矩阵做一些其他的事情。

我想在指定 data= 参数时像 lm 一样徒劳,我可以从字符串列表中提取变量来执行回归——例如,如果我有 var_names(包括变量的函数,例如 "log(x1)""as.factor(x2)"),我可以调用 lm(y ~ as.formula(paste(var_names[5:8], collapse = "+")), data = dt),它会正常执行。

由于函数应用于变量,我的第一直觉——使用 [[——行不通了:

dt[["log(x1)"]] = NULL

更有希望的是评估 j 中的内容,但我也无法让它工作:

dt[ , log(x1)] # is fine, but I don't know how to access this from "log(x1)"
dt[ , "log(x1)"] = "log(x1)" #whomp
dt[ , get("log(x1)")] #Error--looking for object named log(x1), as with [[
dt[ , as.formula("log(x1)")] #getting warmer--looks for x1 in the global environment

我不确定如何为 dt 指定环境;我试图了解为 lm 调用 data= 是如何工作的,但没有取得任何进展。

但是如果 dt 的环境是 envdt,我认为这会起作用:

dt[ , as.formula("log(x1)", env = envdt)]

如果我能让它工作,我将遍历字符向量来得到我的矩阵:

mat <- c()
for (vv in var_names){
   mat <- cbind(mat, dt[ , as.formula(vv, env = envdt)])
}

有人对如何调用正确的环境(即模仿 lm)或以编程方式获取我正在寻找的矩阵的其他方法有任何建议吗?

这里有一个选项,它使用 .SD 作为评估表达式的环境。.SD 表示当前 data.table(或至少当前子组减去分组变量,但由于我们没有分组,它与整个 table):

dt <- data.table(x1=1:10, x2=1:10, x3=1:10)
calls <- expression(x1, log(x1), as.numeric(as.factor(x3)), 3 * x2 - x1)
mx <- as.matrix(dt[, lapply(calls, eval, envir=.SD)])   # <- note `.SD`

colnames(mx) <- sapply(calls, deparse, width=500)       # Make pretty 
mx

生产:

      x1   log(x1) as.numeric(as.factor(x3)) 3 * x2 - x1
 [1,]  1 0.0000000                         1           2
 [2,]  2 0.6931472                         2           4
 [3,]  3 1.0986123                         3           6
 [4,]  4 1.3862944                         4           8
 [5,]  5 1.6094379                         5          10
 [6,]  6 1.7917595                         6          12
 [7,]  7 1.9459101                         7          14
 [8,]  8 2.0794415                         8          16
 [9,]  9 2.1972246                         9          18
[10,] 10 2.3025851                        10          20