如何将数据框列名传入含survival::Surv的自定义函数?
解决coxph自定义函数中列名参数解析问题
错误原因
你遇到的Error in Surv(tte, eventfl) : object 'pfstte' not found,本质是coxph的公式解析环境问题:公式默认在全局环境查找变量,而你的tte和eventfl是函数参数,代表indf的列名,直接写Surv(tte, eventfl)会被当成全局对象,而非数据框的列。
修正后的函数(两种可行方案)
方案1:用tidy eval动态构建公式
利用rlang包的表达式工具,将参数解析为列名后构建公式:
hrdf <- function(indf, tte, eventfl) { # 构建Surv表达式,用{{}}解析列名参数 surv_expr <- rlang::expr(Surv({{tte}}, {{eventfl}})) # 组合成完整的coxph公式 cox_formula <- rlang::new_formula(surv_expr, rlang::expr(ENRLARM_STD)) df <- broom::tidy(coxph(cox_formula, data = indf[indf$SEX == 'Female',], ties = 'efron'), conf.int = TRUE) %>% dplyr::mutate(term = 'Sex', cat = 'Female') return(df) }
方案2:用符号转换拼接公式字符串
这种方式更直观,适合习惯字符串操作的场景:
hrdf <- function(indf, tte, eventfl) { # 将函数参数转换为列名符号 tte_col <- rlang::ensym(tte) event_col <- rlang::ensym(eventfl) # 拼接成公式字符串并转换为公式对象 cox_formula <- as.formula(paste0("Surv(", as.character(tte_col), ", ", as.character(event_col), ") ~ ENRLARM_STD")) df <- broom::tidy(coxph(cox_formula, data = indf[indf$SEX == 'Female',], ties = 'efron'), conf.int = TRUE) %>% dplyr::mutate(term = 'Sex', cat = 'Female') return(df) }
调用方式
直接传入列名(无需加引号)即可:
# 示例:假设数据框为mydata,时间列是pfstte,事件列是pfsevent hrdf(mydata, pfstte, pfsevent)
为什么之前的尝试无效?
{{}}:单独放在Surv(tte, eventfl)里不生效,因为{{}}的解析逻辑主要适配dplyr等tidyverse函数,直接在公式的Surv调用中无法被正确识别;[[]]:如果直接写成Surv(indf[[tte]], indf[[eventfl]]),coxph的公式不接受这种直接传入对象的写法,必须是基于数据框列名的引用;eval()/substitute():如果没结合公式的完整构建(比如只替换了参数但没生成合法的公式对象),会因为环境不匹配导致解析失败。
内容的提问来源于stack exchange,提问作者user2272972
相关产品推荐
相关产品推荐

