通过字符串访问 data.table 字段的函数;或者,如何在 lm 中模仿 data=
Accessing functions of data.table fields via strings; or, how to imitate data= in lm
我正在尝试构建一个从 data.table
字段派生的变量矩阵;
为了具体起见,假设我有一个带有变量 x1
、x2
、x3
的 data.table dt
,我想使 nrow(dt)
x4 矩阵,列为 x1
、log(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
我正在尝试构建一个从 data.table
字段派生的变量矩阵;
为了具体起见,假设我有一个带有变量 x1
、x2
、x3
的 data.table dt
,我想使 nrow(dt)
x4 矩阵,列为 x1
、log(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