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

5

我想使用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)))

但这并不起作用,因为替代品没有评估它的第一个参数。因此,我只会得到原始变量:

expr1

现在这里说,如果我想在分配给变量的表达式中进行替换,我需要执行两次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)
})
3个回答

7

这似乎解决了问题

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()来避免“拆箱”。

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

这两个将返回一个类型为"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)
# })

非常感谢。你和Small提供的两个解决方案都生成了一个“if”类对象。实际上,我确实想将其保留为表达式,但是当我像建议的那样包装expr2(即:expression(expr2)),然后我得到的是“expression(expr2)”,而不是“expression(if(cos(x))...)”。显然,我没有正确地进行包装。有什么指导吗? - user3990797
@user3990797 抱歉,我的意思是你可以在 do.call() 周围使用 as.expression()。我已经更新了我的答案。 - MrFlick
没问题,很高兴能帮忙并学到了一些东西。我也会在我的答案中添加 as.expression() 的注释。 - small_data88

0

您需要通过将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)


3
需要在那儿加上一个 x= 吗?我复制/粘贴了这段代码,但对我没有任何改变。还是 if(x) - MrFlick
嗯,这很奇怪,我刚刚再次运行它,现在返回的表达式没有cos(x)。不知道发生了什么事,正在尝试修复:/ - small_data88
@MrFlick 我现在明白了 :) - small_data88
@small_data88:谢谢!请看上面MrFlick的评论。 - user3990797

0

另一种选择可能是:

x <- expr(cos(x)) 

expr2 <- expr(if (!!x) {
                return(y)
                 } else {
                 return(z) })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接