【问题标题】:Using substitute to do variable substitutions inside R expressions使用替换在 R 表达式中进行变量替换
【发布时间】:2015-07-13 01:23:37
【问题描述】:

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

现在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)
})

【问题讨论】:

    标签: r expression substitution


    【解决方案1】:

    这似乎可以解决问题

    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)
    # })
    

    【讨论】:

    • 非常感谢。两种解决方案(您的和小型的)都会产生一个“if”类​​对象。实际上,我确实希望将其保留为一个表达式,但是当我按照建议包装 expr2 (即: expression(expr2) )时,我得到的是 "expression(expr2)" 而不是 "expression(if(cos(x)) ...)”。显然我没有正确包装。有什么指导吗?
    • @user3990797 抱歉。我的意思是你可以在do.call() 周围使用as.expression()。我已经更新了我的答案。
    • 没问题,很高兴能提供帮助并学到了一些东西。我也在我的答案中添加了as.expression() 注释。
    【解决方案2】:

    您必须通过将cos(x) 包装在嵌套substitution() 的x = quote() 函数中来添加cos(x) 添加:根据文档,您可以使用[、[[ 或$ 对表达式进行子集化。您必须在超级替换调用中使用 [[ 对表达式对象进行子集化。试试这个:

    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=吗?我复制/粘贴了这个,但它对我没有任何改变。还是if(x)
    • 嗯,这很奇怪,我刚刚再次运行它,现在它返回了没有 cos(x) 的表达式。不知道怎么回事,马上修复:/
    • @MrFlick 我想我现在明白了 :)
    • @small_data88:谢谢!请参阅上面关于 MrFlick 的评论。
    【解决方案3】:

    另一种可能是:

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

    【讨论】:

      猜你喜欢
      • 2015-06-28
      • 1970-01-01
      • 2019-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-25
      相关资源
      最近更新 更多