我最近一直在处理CDISC数据,这些数据是由预先指定的列名和对生存数据编码方式的某些期望组成的。
我想为survival::Surv()
编写一个使用CDISC格式的结构化数据的包装器。我有一个在大多数情况下工作的函数,但我不能让它与survival::coxph()
一起工作。
如何让我的Surv()
包装器函数使用默认值并在coxph()
中工作?下面是使用visR::adtte
数据集的示例(数据集随visR软件包一起提供)。安装devtools::install_github("openpharma/visR")
),这是在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
由reprex包(v2.0.1)创建于2022-06-05
这看起来像是survival
包中的一个错误,或者可能是误用它(我不太熟悉内部)。
编辑添加注释:
我认为下面的分析是错误的。仔细阅读代码,我认为survival
包中的当前代码将无法可靠地工作,除非您在公式中使用显式的Surv(AVAL, CNSR)
。
下面的分析似乎是有效的,但我不相信它:
问题是survival:::terms.inner
专门寻找一个名为Surv
的函数,在这里:https://github.com/therneau/survival/blob/b5238a42867a931954cf222b871a7b3a1c2fcd24/R/xtras.R#L65。因为你的函数有一个不同的名字,所以它不会被当作是同一件事来处理。
您可以通过将函数命名为Surv
来修复此问题。当我这样做的时候,事情似乎起作用了。当然,这可能会导致其他地方的问题,当你想要原始的Surv
没有survival::
前缀,但我不知道一个方法来解决这个问题。
我仍然担心使用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)
这个没有你的通用,但我认为它更安全。