【问题标题】:Using tidy selection together with the survival package - "Error: promise already under evaluation"将整洁的选择与生存包一起使用 - “错误:承诺已在评估中”
【发布时间】:2021-11-04 15:01:17
【问题描述】:

我正在编写一个 R 函数,它允许用户在创建 survival::survfit 对象时指定一个单独的时间变量。 survival 包具有“无字符串”语法,这意味着时间变量的名称(在我的例子中是“dtime”)不需要任何引号:

survival::survfit(formula = survival::Surv(dtime, death) ~ 1, rotterdam)

因此,我认为我可以使用 tidy 评估来达到我的目的。这是我的代码:

# My function
get_survfit <- function(.data, .time){
  return(survival::survfit(formula = survival::Surv({{ .time }}, status) ~ 1, .data))
}

# Application example
library(survival)
data(cancer)
rotterdam
colnames(rotterdam)[which(names(rotterdam) == "death")] = "status"
get_survfit(.data=rotterdam, .time=dtime)

但是,我总是收到以下错误:

生存错误::Surv({ : object 'dtime' not found

在调试器中查看“dtime”时,我得到:

总结时出错: 已在评估中的承诺:递归默认参数引用或更早 有问题吗?

我怎样才能解决这个问题并仍然获得我的功能?

【问题讨论】:

    标签: r dplyr tidyeval survival


    【解决方案1】:

    survfit() 不是一个整洁的 eval 函数,因此您在上下文之外使用 {{。见https://rlang.r-lib.org/reference/topic-inject-out-of-context.html

    相反,您需要使用inject() 来启用从外部注入。由于survfit() 不是一个整洁的评估函数,它不支持{{ 创建的quosures。所以你需要使用!!ensym()

    get_survfit <- function(data, time) {
      time <- ensym(time)
    
      inject(
        survival::survfit(formula = survival::Surv(!!time, status) ~ 1, data)
      )
    }
    

    ensym() 确保传递简单的变量名,并将它们解散。 !! 在公式中注入变量。

    【讨论】:

      【解决方案2】:

      基于 Lionel Henry 的回答并受到 another question I asked 的启发,我想补充一点,enquoget_expr 也可以达到相同的结果:

      get_survfit <- function(.data, .time){
        .time = rlang::enquo(.time)
        .time = rlang::get_expr(.time)
        
        rlang::inject(
          return(survival::survfit(formula = survival::Surv(!!.time, status) ~ 1, .data))
        )
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-23
        • 1970-01-01
        • 2017-10-20
        • 2020-04-28
        • 2017-09-20
        • 2021-01-08
        • 2011-03-05
        • 2018-06-10
        相关资源
        最近更新 更多