为“生存:: surv()编写包装器功能,默认值

发布于 2025-02-04 10:01:09 字数 3216 浏览 3 评论 0 原文

我最近一直在使用具有预先指定的列名称以及对生存数据编码方式的某些期望来构建的CDISC数据。

我想为使用CDISC格式的结构化数据编写一个生存:: surv()的包装器。我的功能在大多数情况下都可以使用,但是我无法将其与生存:: coxph()一起使用。

如何获得我的 surv()包装器函数以使用默认值并在 coxph()中工作?以下是使用 visr :: adtte 数据集的示例,以CDISC格式。除最后一个示例外,所有示例都没有问题。

Surv_CDISC <- function(AVAL, CNSR) {
  # set default values if not passed by user -----------------------------------
  if (missing(AVAL) && exists("AVAL", envir = rlang::caller_env()))
    AVAL <- get("AVAL", envir = rlang::caller_env())
  else if (missing(AVAL))
    stop("Default 'AVAL' value not found. Specify argument in `Surv_CDISC(AVAL=)`.")
  if (missing(CNSR) && exists("CNSR", envir = rlang::caller_env()))
    CNSR <- get("CNSR", envir = rlang::caller_env())
  else if (missing(CNSR))
    stop("Default 'CNSR' value not found. Specify argument in `Surv_CDISC(CNSR=)`.")
  
  # pass args to `survival::Surv()` --------------------------------------------
  survival::Surv(time = AVAL, event = 1 - CNSR)
}


# passing the arguments, everything works
with(visR::adtte, Surv_CDISC(AVAL = AVAL, CNSR = CNSR)) |> head()
#> [1]  2   3   3  28+ 58  46+
# letting the arguments use default value, everything still works
with(visR::adtte, Surv_CDISC()) |> head()
#> [1]  2   3   3  28+ 58  46+


# using function in model.frame() and defining argument values, everything works
model.frame(Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte) |> head(n = 2)
#>   Surv_CDISC(AVAL, CNSR) SEX
#> 1                      2   F
#> 2                      3   M
# using function in model.frame() with default arguments, everything works
model.frame(Surv_CDISC() ~ SEX, data = visR::adtte) |> head(n = 2)
#>   Surv_CDISC() SEX
#> 1            2   F
#> 2            3   M


# using function in survfit() and defining argument values, everything works
survival::survfit(Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> Call: survfit(formula = Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> 
#>         n events median 0.95LCL 0.95UCL
#> SEX=F 143     80     64      47      96
#> SEX=M 111     72     41      30      57
# using function in survfit() with default arguments, everything works
survival::survfit(Surv_CDISC() ~ SEX, data = visR::adtte)
#> Call: survfit(formula = Surv_CDISC() ~ SEX, data = visR::adtte)
#> 
#>         n events median 0.95LCL 0.95UCL
#> SEX=F 143     80     64      47      96
#> SEX=M 111     72     41      30      57


# using function in coxph() and defining argument values, everything works
survival::coxph(Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> Call:
#> survival::coxph(formula = Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> 
#>        coef exp(coef) se(coef)     z     p
#> SEXM 0.3147    1.3699   0.1626 1.935 0.053
#> 
#> Likelihood ratio test=3.71  on 1 df, p=0.05412
#> n= 254, number of events= 152
# DOES NOT WORK TRYING TO RELY ON DEFAULT VALUES
survival::coxph(Surv_CDISC() ~ SEX, data = visR::adtte)
#> Error in x[[2]]: subscript out of bounds

I've been working recently with CDISC data that is structured with pre-specified column names and certain expectations for the way survival data are coded.

I want to write a wrapper for survival::Surv() that uses the structured data of the CDISC format. I have a function that is working in most scenarios, but I can't get it to work with survival::coxph().

How can I get my Surv() wrapper function to use default values and work in coxph()? Below are examples using the visR::adtte data set (data set ships with the visR package...install with devtools::install_github("openpharma/visR")), which is in CDISC format. All examples run without issue except the last one.

Surv_CDISC <- function(AVAL, CNSR) {
  # set default values if not passed by user -----------------------------------
  if (missing(AVAL) && exists("AVAL", envir = rlang::caller_env()))
    AVAL <- get("AVAL", envir = rlang::caller_env())
  else if (missing(AVAL))
    stop("Default 'AVAL' value not found. Specify argument in `Surv_CDISC(AVAL=)`.")
  if (missing(CNSR) && exists("CNSR", envir = rlang::caller_env()))
    CNSR <- get("CNSR", envir = rlang::caller_env())
  else if (missing(CNSR))
    stop("Default 'CNSR' value not found. Specify argument in `Surv_CDISC(CNSR=)`.")
  
  # pass args to `survival::Surv()` --------------------------------------------
  survival::Surv(time = AVAL, event = 1 - CNSR)
}


# passing the arguments, everything works
with(visR::adtte, Surv_CDISC(AVAL = AVAL, CNSR = CNSR)) |> head()
#> [1]  2   3   3  28+ 58  46+
# letting the arguments use default value, everything still works
with(visR::adtte, Surv_CDISC()) |> head()
#> [1]  2   3   3  28+ 58  46+


# using function in model.frame() and defining argument values, everything works
model.frame(Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte) |> head(n = 2)
#>   Surv_CDISC(AVAL, CNSR) SEX
#> 1                      2   F
#> 2                      3   M
# using function in model.frame() with default arguments, everything works
model.frame(Surv_CDISC() ~ SEX, data = visR::adtte) |> head(n = 2)
#>   Surv_CDISC() SEX
#> 1            2   F
#> 2            3   M


# using function in survfit() and defining argument values, everything works
survival::survfit(Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> Call: survfit(formula = Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> 
#>         n events median 0.95LCL 0.95UCL
#> SEX=F 143     80     64      47      96
#> SEX=M 111     72     41      30      57
# using function in survfit() with default arguments, everything works
survival::survfit(Surv_CDISC() ~ SEX, data = visR::adtte)
#> Call: survfit(formula = Surv_CDISC() ~ SEX, data = visR::adtte)
#> 
#>         n events median 0.95LCL 0.95UCL
#> SEX=F 143     80     64      47      96
#> SEX=M 111     72     41      30      57


# using function in coxph() and defining argument values, everything works
survival::coxph(Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> Call:
#> survival::coxph(formula = Surv_CDISC(AVAL, CNSR) ~ SEX, data = visR::adtte)
#> 
#>        coef exp(coef) se(coef)     z     p
#> SEXM 0.3147    1.3699   0.1626 1.935 0.053
#> 
#> Likelihood ratio test=3.71  on 1 df, p=0.05412
#> n= 254, number of events= 152
# DOES NOT WORK TRYING TO RELY ON DEFAULT VALUES
survival::coxph(Surv_CDISC() ~ SEX, data = visR::adtte)
#> Error in x[[2]]: subscript out of bounds

Created on 2022-06-05 by the reprex package (v2.0.1)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最丧也最甜 2025-02-11 10:01:09

这看起来像是生存软件包中的一个错误,或者可能误用了(我对内部设备并不那么熟悉)。

编辑以添加评论:

我认为以下分析是错误的。更仔细地读取代码,我认为生存软件包中的当前代码除非您在公式中使用显式 surch(aval,cnsr),否则不会可靠地工作。

这是似乎有效的分析,但我不信任它:

问题是生存::: terms.inner 专门寻找名为 surch 的函数,此处:。由于您的函数具有不同的名称,因此它并没有处理好像是同一件事。

您也可以通过将函数命名 surch 来解决此问题。当我这样做时,事情似乎有效。当然,当您想要原始 surv 而没有生存>: 前缀时,这可能会导致其他地方的问题,但我不知道一种解决这个问题的方法。

我仍然担心使用 caller_env()。这是我创建您的假 surv 的方式:

make_surv_CDISC <- function(defaults) {

  force(defaults)
  
  function(AVAL = defaults$AVAL, 
           CNSR = defaults$CNSR) {
    
  # pass args to `survival::Surv()` --------------------------------------------
    survival::Surv(time = AVAL, event = 1 - CNSR)
  }
}

Surv <- make_surv_CDISC(visR::adtte)

这比您的概括不多,但我认为这更安全。

This looks like a bug in the survival package, or maybe a mis-use of it (I'm not so familiar with the internals).

EDITED TO ADD A COMMENT:

I think the analysis below is wrong. Reading the code more carefully, I think the current code in the survival package won't work reliably unless you use the explicit Surv(AVAL, CNSR) in the formula.

HERE'S THE ANALYSIS THAT APPEARED TO WORK, BUT I DON'T TRUST IT:

The problem is that survival:::terms.inner looks specifically for a function named Surv, here: https://github.com/therneau/survival/blob/b5238a42867a931954cf222b871a7b3a1c2fcd24/R/xtras.R#L65 . Since your function has a different name, it's not handled as if it is the same thing.

You could fix this by naming your function Surv as well. When I do that, things appear to work. Of course, this may cause problems elsewhere when you want the original Surv without the survival:: prefix, but I don't know a way to fix that.

I'd still worry about using caller_env(). Here's how I'd create your fake Surv:

make_surv_CDISC <- function(defaults) {

  force(defaults)
  
  function(AVAL = defaults$AVAL, 
           CNSR = defaults$CNSR) {
    
  # pass args to `survival::Surv()` --------------------------------------------
    survival::Surv(time = AVAL, event = 1 - CNSR)
  }
}

Surv <- make_surv_CDISC(visR::adtte)

This is less general than yours, but I think it's safer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文