使用 substitute 在 R 表达式中进行变量替换
Using substitute to do variable substitutions inside R expressions
我想使用 substitute()
在表达式中进行变量替换,而不计算表达式。例如,我有:
expr1 <- expression(if(x){
return(y)
} else {
return(z)
})
我想做的是将以下结果分配给 "expr1":
expression(if(cos(x)){
return(y)
} else {
return(z)
})
通过这样做:
expr2 <- substitute(expr1, list(x=cos(x)))
但这不起作用,因为 substitute 不计算它的第一个参数。所以我只取回原始变量:
expr1
现在 here 它说要在分配给变量的表达式中进行替换,我必须执行 substitute()
两次,然后是 eval()
,如下所示:
expr2 <- eval(substitute(substitute(e, list(x = cos(x))), list(e = expr1)))
当我执行此语句时,我确实得到了一个分配给 "expr2" 的表达式,但它不包含所需的替换:
expression(if (x) {
return(y)
} else {
return(z)
})
我可以对 "expr1" 应用什么语法,以便得到我想要分配给 "expr2" 的结果,即:
expression(if (cos(x)) {
return(y)
} else {
return(z)
})
这似乎可以解决问题
do.call('substitute', list(expr1[[1]], list(x=quote(cos(x)))))
# if (cos(x)) {
# return(y)
# } else {
# return(z)
# }
首先,我使用 do.call
将未计算的表达式作为参数传递给 substitute()
,而不是双 substitute
。其次,expression()
真的很像一个容器对象。您真正感兴趣的只是更改表达式第一个元素的代码块。您本可以避免 expression()
并使用 quote()
来避免 "unboxing"
expr2 <- quote(if(x){ return(y) } else { return(z) })
do.call('substitute', list(expr2, list(x=quote(cos(x)))))
这两个都将 return 类型为 "if" 的 class。如果需要,可以将其包装在 as.expression()
.
中
as.expression(do.call('substitute', list(expr1[[1]], list(x=quote(cos(x))))))
# expression(if (cos(x)) {
# return(y)
# } else {
# return(z)
# })
您必须通过将 cos(x)
包装在嵌套 substitution()
的 x = quote()
函数中来添加添加:根据文档,您可以使用 [
对表达式进行子集化, [[
,或 $
。您必须在超级替换调用中使用 [[
对表达式对象进行子集化。试试这个:
expr2 <- eval(substitute(substitute(e, list(x=quote(cos(x)))), list(e = expr1[[1]])))
expr2
#if (cos(x)) {
# return(y)
#} else {
# return(z)
#}
要将 expr2
设置为表达式,请调用:as.expression(expr2)
备选方案可能是:
x <- expr(cos(x))
expr2 <- expr(if (!!x) {
return(y)
} else {
return(z) })
我想使用 substitute()
在表达式中进行变量替换,而不计算表达式。例如,我有:
expr1 <- expression(if(x){
return(y)
} else {
return(z)
})
我想做的是将以下结果分配给 "expr1":
expression(if(cos(x)){
return(y)
} else {
return(z)
})
通过这样做:
expr2 <- substitute(expr1, list(x=cos(x)))
但这不起作用,因为 substitute 不计算它的第一个参数。所以我只取回原始变量:
expr1
现在 here 它说要在分配给变量的表达式中进行替换,我必须执行 substitute()
两次,然后是 eval()
,如下所示:
expr2 <- eval(substitute(substitute(e, list(x = cos(x))), list(e = expr1)))
当我执行此语句时,我确实得到了一个分配给 "expr2" 的表达式,但它不包含所需的替换:
expression(if (x) {
return(y)
} else {
return(z)
})
我可以对 "expr1" 应用什么语法,以便得到我想要分配给 "expr2" 的结果,即:
expression(if (cos(x)) {
return(y)
} else {
return(z)
})
这似乎可以解决问题
do.call('substitute', list(expr1[[1]], list(x=quote(cos(x)))))
# if (cos(x)) {
# return(y)
# } else {
# return(z)
# }
首先,我使用 do.call
将未计算的表达式作为参数传递给 substitute()
,而不是双 substitute
。其次,expression()
真的很像一个容器对象。您真正感兴趣的只是更改表达式第一个元素的代码块。您本可以避免 expression()
并使用 quote()
来避免 "unboxing"
expr2 <- quote(if(x){ return(y) } else { return(z) })
do.call('substitute', list(expr2, list(x=quote(cos(x)))))
这两个都将 return 类型为 "if" 的 class。如果需要,可以将其包装在 as.expression()
.
as.expression(do.call('substitute', list(expr1[[1]], list(x=quote(cos(x))))))
# expression(if (cos(x)) {
# return(y)
# } else {
# return(z)
# })
您必须通过将 cos(x)
包装在嵌套 substitution()
的 x = quote()
函数中来添加添加:根据文档,您可以使用 [
对表达式进行子集化, [[
,或 $
。您必须在超级替换调用中使用 [[
对表达式对象进行子集化。试试这个:
expr2 <- eval(substitute(substitute(e, list(x=quote(cos(x)))), list(e = expr1[[1]])))
expr2
#if (cos(x)) {
# return(y)
#} else {
# return(z)
#}
要将 expr2
设置为表达式,请调用:as.expression(expr2)
备选方案可能是:
x <- expr(cos(x))
expr2 <- expr(if (!!x) {
return(y)
} else {
return(z) })