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