使用替换在R表达式中进行变量替换

use*_*797 5 expression r substitution

我想用来substitute()在表达式中做变量替换,而不用计算表达式.例如,我有:

expr1 <- expression(if(x){
    return(y)
} else {
    return(z)
})
Run Code Online (Sandbox Code Playgroud)

我想要做的是将以下结果分配给"expr1":

expression(if(cos(x)){
    return(y)
} else {
    return(z)
 })
Run Code Online (Sandbox Code Playgroud)

做这样的事情:

expr2 <- substitute(expr1, list(x=cos(x)))
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为替补不会评估它的第一个论点.所以我回到原始变量:

expr1
Run Code Online (Sandbox Code Playgroud)

现在这里说它要在分配给变量的表达式中进行替换,我必须执行substitute()两次,然后执行eval(),如下所示:

expr2 <- eval(substitute(substitute(e, list(x = cos(x))), list(e = expr1)))
Run Code Online (Sandbox Code Playgroud)

当我执行此语句时,我确实得到一个分配给"expr2"的表达式,但它不包含所需的替换:

expression(if (x) {
    return(y)
} else {
    return(z)
})
Run Code Online (Sandbox Code Playgroud)

我可以将什么语法应用于"expr1",以便获得我想要分配给"expr2"的结果,即:

expression(if (cos(x)) {
    return(y)
} else {
    return(z)
})
Run Code Online (Sandbox Code Playgroud)

MrF*_*ick 6

这似乎可以解决问题

do.call('substitute', list(expr1[[1]], list(x=quote(cos(x)))))
# if (cos(x)) {
#     return(y)
# } else {
#     return(z)
# }
Run Code Online (Sandbox Code Playgroud)

首先,我使用do.call未计算的表达式作为参数传递给substitute()而不是 double- substitute。其次,expression()真的很像一个容器对象。您真正感兴趣的是仅更改表达式的第一个元素的代码块。你本可以避免expression()并且只是用来quote()避免“拆箱”

expr2 <- quote(if(x){ return(y) } else { return(z) })
do.call('substitute', list(expr2, list(x=quote(cos(x)))))
Run Code Online (Sandbox Code Playgroud)

这两个都将返回一个类型为“if”的类。如果需要,您可以将其包装在as.expression().

as.expression(do.call('substitute', list(expr1[[1]], list(x=quote(cos(x))))))
# expression(if (cos(x)) {
#     return(y)
# } else {
#     return(z)
# })
Run Code Online (Sandbox Code Playgroud)