编写带默认值的survival::Surv()包装函数适配coxph()调用
问题根因
survival::coxph()和survfit()、model.frame()的处理逻辑存在差异:后者会先在提供的data环境中完整求值公式左侧的表达式,直接拿到Surv对象结果做后续计算,不会解析表达式本身的结构,因此原函数通过caller_env()查找变量的逻辑可以正常运行。coxph()会在求值前先解析公式左侧生存对象的调用语句,尝试从调用的参数位置提取时间、事件对应的变量名做内部校验。当传入Surv_CDISC()无参调用时,coxph解析这个调用的参数列表时发现第二个位置没有内容,执行x[[2]]取值时就会触发下标越界错误。
修复方法
不要手动在函数内部通过调用环境查找默认值,改为使用和CDISC标准列名一致的延迟求值默认参数,同时保留函数调用的参数结构,让coxph可以正常识别变量,同时兼容所有原有使用场景:
Surv_CDISC <- function(AVAL = AVAL, CNSR = CNSR) { # 匹配实际传入的调用参数 matched_call <- match.call() # 构造标准Surv调用,自动转换CDISC删失编码(CNSR=1为删失,事件指示为1-CNSR) surv_expr <- quote(survival::Surv(time = AVAL, event = 1 - CNSR)) # 将用户传入的参数替换到标准调用中 surv_expr$AVAL <- matched_call$AVAL surv_expr$CNSR <- matched_call$CNSR # 在父环境(即data对应的求值环境)中执行计算 eval(surv_expr, envir = parent.frame()) }
验证结果
修复后所有场景均可正常运行,包括之前报错的无参coxph()调用:
# 之前报错的无参coxph调用 survival::coxph(Surv_CDISC() ~ SEX, data = visR::adtte)
运行输出:
Call: survival::coxph(formula = Surv_CDISC() ~ 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
其余原测试场景(with()调用、显式传参、model.frame()、survfit())均保持兼容,运行结果和预期一致。
内容的提问来源于stack exchange,提问作者Daniel D. Sjoberg
相关产品推荐
相关产品推荐

