首页 > 解决方案 > 如何在基本 R 公式中使用类似 quosure 的语法?

问题描述

我想写一个这样的函数:

library(survival)
getFit = function(x, data){
  survfit(Surv(start, stop, event) ~ x, data = data)
}
getFit(surgery, heart)
getFit("surgery", heart) #if not possible, this would be fine too

当然,x不读。请注意,我使用survfitwithheart作为示例,但我对几乎每个基于公式的函数(lm、glm 等)都遇到了这个问题。

我知道我可以用pasteand写一些东西as.formula,但我想知道是否有类似我会做的tidyverse事情,比如:

getSurvPlot = function(x, data=db){
  xx = enquo(x)
  survfit(Surv(start, stop, event) ~ !!xx, data = data)
}

最后一个代码也不起作用,但我认为这是因为survfit它不是tidyverse.

有没有什么干净的方法可以在 base R 中写出这样的东西?

编辑:在这个例子中,我现在将使用survminer::surv_fit,它是一个包装器,survfit允许在公式中具有更大的灵活性。

标签: rformulatidyverse

解决方案


Moody_mudskipper 给出了非常详细的答案。我只是想指出您的定义getSurvPlot几乎是正确的。您的问题不在于 rlang/tidyverse,而是在另一个公式中使用引用的参数(这是一个公式)。

调用 时getSurvPlot(surgery, heart)enquo会将第一个参数捕获为~surgery,这已经是一个公式。无需使用~和 创建新公式xxSurv您只需更新已有公式的左侧即可。这可以使用stats::update()基础 R 来完成:

getSurvPlot <- function(x, data=db){
  xx <- enquo(x)
  survfit(stats::update( xx, Surv(start, stop, event) ~ . ), data = data)
}

getSurvPlot(surgery, heart)现在应该按预期工作。

正如@Moody_mudskipper 所指出的,实际工作由 完成stats::update.formula(),这是公式对象的S3 泛型 stats::update()的实现,例如xx.


推荐阅读