Having similar problem, I am looking for a more generalized solution than the one provided for this question: How do I substitute symbols in a language object?
I have an unevaluated expression foo <- quote(bar + baz), which is a variable inside other expression: qux <- quote(bla + foo).
We can check that:
exists("foo", envir=.GlobalEnv) & class(foo)=="call"
[1] TRUE
exists("qux", envir=.GlobalEnv) & class(qux)=="call"
[1] TRUE
Now I would like to write a generalized function that decomposes (parses?) qux into the component expressions and replaces the ones that exist in the .GlobalEnv and that are of class call with their values:
replaceFUN <- function(x) {
# do something
}
Running replaceFUN(qux) should return:
bla + (bar + baz)
Background on the actual problem:
I am building a quant trading rules backtesting engine. My aim is to delay evaluation of the quote()d expressions, such as rules and indicator calculations later after their definition.
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
This obviously raises an error because AddColumn function lacks the mechanism to parse the nested moving.average and time.filter variables (plus and any other that user defines and nests). The nesting of rules inside buy is done for readability and is indeed a syntactic sugar.
I was solving a very similar problem to this a little while ago. Check out the source code of [.data.table and look at the deconstruct_and_eval and construct functions there. It should give you enough info to go on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With