R 用于替换quote()d表达式中的所有变量(如果它们存在于环境中)的通用函数
对于类似的问题,我正在寻找一个比为这个问题提供的更普遍的解决方案:R 用于替换quote()d表达式中的所有变量(如果它们存在于环境中)的通用函数,r,R,对于类似的问题,我正在寻找一个比为这个问题提供的更普遍的解决方案: 我有一个未赋值的表达式foo我刚才正在解决一个与此非常类似的问题。查看[.data.table中的并查看那里的解构和评估和构造函数。它应该为您提供足够的信息以继续操作。从 产生所需的一般解决方案: deconstruct_and_eval = function(expr, envir = parent.frame(), enclos = parent.frame()) { if (!mode(expr) %in% c("c
我有一个未赋值的表达式
foo我刚才正在解决一个与此非常类似的问题。查看[.data.table
中的并查看那里的解构和评估和构造
函数。它应该为您提供足够的信息以继续操作。从
产生所需的一般解决方案:
deconstruct_and_eval = function(expr, envir = parent.frame(), enclos = parent.frame()) {
if (!mode(expr) %in% c("call", "expression"))
return(expr)
if (length(expr) == 1) {
if (is.call(expr[[1]])) return (deconstruct_and_eval(expr[[1]]))
else return(expr)
}
if (expr[[1]] == quote(eval) && length(expr) < 3) {
return(deconstruct_and_eval(eval(expr[[2]], envir, enclos), envir, enclos))
}
lapply(expr, function(m) {
if (is.call(m)) {
if (m[[1]] == quote(eval)) eval(m[[2]], envir, enclos)
else deconstruct_and_eval(m, envir, enclos)
} else {
# begin edit
if(exists(as.character(m),envir=.GlobalEnv)) {
if(!is.function(eval(m)))
eval(m)
else
m
} else
# end edit
m
}
})
}
然后可以使用construct
函数从以下位置重建此解构列表:
实际问题的应用:
deconstruct_and_eval(buy)
[[1]]
`&`
[[2]]
[[2]][[1]]
`>`
[[2]][[2]]
Close
[[2]][[3]]
SMA(Close, nSMA)
[[3]]
Date == t
construct(deconstruct_and_eval(buy))
Close > SMA(Close, nSMA) & Date == t
在您的例子中:do.call(substitute,list(qux,list(foo=foo)))
谢谢Joshua,这当然有助于解决问题的替换部分。问题的另一部分是如何将qux
表达式分解为组件,以便在.GlobalEnv
中搜索,以及在do.call中填充列表的匹配项(替换,列表(qux,list(foo=foo))
首先想到的是strsplit()
,但我事先不知道拆分
的参数。也许我应该编辑我的问题,将问题分解成几个部分。与其将问题分解成几个部分,不如您提供一些您试图解决的实际问题的背景。可能有一种比搜索和替换调用更简单的方法。请看t如何处理延迟的评估。或者,更好的是,对quantstrat作出贡献,而不是重新创建类似的东西。现场,我修改了您指出的解构和评估
函数,它工作了!请参阅我的详细答案。对于环境中存在的对象和至少没有函数。由于您的答案提供了一个关键线索,我很高兴地将此设置为已接受的答案,并在单独的部分中提供了繁琐的细节。请注意,解构和评估
不再出现在包源代码中,它已在1.9.7中删除,因此任何查找它的人都应检查1.9.6
bla + (bar + baz)
require(data.table)
require(TTR) # for the `SMA` function
DT <- data.table(Instrument=rep("SPX",3),Date=1:3, Close=c(1050, 1052, 1051))
# define parameters
nSMA <-2
t <- 2
# define indicators
time.filter <- quote( Date==t )
moving.average <- quote( SMA(Close, nSMA) )
buy <- quote( Close > moving.average & time.filter )
AddColumn <- function(x, colname) {
DT[,eval(substitute(colname)):=eval(x, envir=.SD)]
}
AddColumn(time.filter, "filter")
Instrument Date Close filter
1: SPX 1 1050 FALSE
2: SPX 2 1052 TRUE
3: SPX 3 1051 FALSE
AddColumn(moving.average, "MA")
Instrument Date Close filter MA
1: SPX 1 1050 FALSE NA
2: SPX 2 1052 TRUE 1051.0
3: SPX 3 1051 FALSE 1051.5
AddColumn(buy, "Buy")
Error in Close > moving.average & time.filter :
operations are possible only for numeric, logical or complex types
deconstruct_and_eval = function(expr, envir = parent.frame(), enclos = parent.frame()) {
if (!mode(expr) %in% c("call", "expression"))
return(expr)
if (length(expr) == 1) {
if (is.call(expr[[1]])) return (deconstruct_and_eval(expr[[1]]))
else return(expr)
}
if (expr[[1]] == quote(eval) && length(expr) < 3) {
return(deconstruct_and_eval(eval(expr[[2]], envir, enclos), envir, enclos))
}
lapply(expr, function(m) {
if (is.call(m)) {
if (m[[1]] == quote(eval)) eval(m[[2]], envir, enclos)
else deconstruct_and_eval(m, envir, enclos)
} else {
# begin edit
if(exists(as.character(m),envir=.GlobalEnv)) {
if(!is.function(eval(m)))
eval(m)
else
m
} else
# end edit
m
}
})
}
deconstruct_and_eval(qux)
[[1]]
`+`
[[2]]
bla
[[3]]
bar + baz
construct(deconstruct_and_eval(qux))
bla + (bar + baz)
deconstruct_and_eval(buy)
[[1]]
`&`
[[2]]
[[2]][[1]]
`>`
[[2]][[2]]
Close
[[2]][[3]]
SMA(Close, nSMA)
[[3]]
Date == t
construct(deconstruct_and_eval(buy))
Close > SMA(Close, nSMA) & Date == t