当在父函数之外使用 as.formula() 时,R 模型会中断

问题描述 投票:0回答:2

我正在尝试将

coxph
模型放入函数中,如下所示:

data(cancer, package="survival") # Import `mgus2` data
ndata <- expand.grid(sex=c("F", "M"), age=c(60, 80))

# Fit Cox PH model and run survfit
fit_cox <- function(df) {
    msfit <- coxph(Surv(futime, death) ~ sex + age, data=df, id=id)
    mssurv <- survfit(msfit, newdata=ndata)
}

fit_cox(mgus2)

如果我想将公式

Surv(futime, death) ~ sex + age
定义为字符串并使用
as.formula()
将其传递给我的模型,就会出现问题。

如果对

as.formula
的调用位于
fit_cox
函数之外,则对
survfit
的调用会中断:

my_formula <- as.formula("Surv(futime, death) ~ sex + age")

# Fit Cox PH model and run survfit
fit_cox <- function(df) {
    msfit <- coxph(my_formula, data=df, id=id)
    mssurv <- survfit(msfit, newdata=ndata)
}

> fit_cox(mgus2)
> Error in model.frame.default(formula = Surv(futime, death) ~ sex + age,  : 
> 'data' must be a data.frame, environment, or list

当对

as.formula
的调用移至
fit_cox
函数中时,不会出现此问题。

fit_cox <- function(df) {
    my_formula <- as.formula("Surv(futime, death) ~ sex + age") # Moved this inside
    msfit <- coxph(my_formula, data=df, id=id)
    mssurv <- survfit(msfit, newdata=ndata)
}

> fit_cox(mgus2)
> # Successful

我想知道这是否不是与实现

survival
coxph
survfit
包有关的特定于包的问题。相反,它可能与
as.formula
通话有关。

将其放在函数内部而不是外部有什么区别?

r
2个回答
1
投票

解释为什么会发生这种情况很棘手,我不太确定我是否完全了解这里发生的情况,但解决方案是使用

do.call
来运行这样的函数:

fit_cox <- function(df) {
  msfit <- do.call("coxph", list(formula=my_formula, 
                                 data=substitute(df), 
                                 id=as.name("id")))
  mssurv <- survfit(msfit, newdata=ndata)
  mssurv
}

该问题与调用的构造方式有关;在你的函数中,调用中有你的变量

do_cox1 <- function(df) {
  coxph(my_formula, data=df, id=id)
}
do_cox1(mgus2)
# Call:
# coxph(formula = my_formula, data = df, id = id)

但是,如果使用

do.call
(首先计算结果),则可以使用
substitute
获取数据变量的名称,从而获得变量的实际值。

do_cox2 <- function(df) {
  do.call("coxph", list(formula=my_formula, 
                        data=substitute(df), 
                        id=as.name("id")))
}
do_cox2(mgus2)
# Call:
# coxph(formula = Surv(futime, death) ~ sex + age, data = mgus2, id = id)

请参阅此答案了解另一个示例。


0
投票

这是 R 中模型框架构建方式的一般“特征”。这是我们遇到麻烦时的调用堆栈:

where 1: model.frame.coxph(object)
where 2: stats::model.frame(object)
where 3: survfit.coxph(msfit, newdata = ndata)
where 4 at #3: survfit(msfit, newdata = ndata)
where 5: fit_cox(mgus2)

这是抛出错误的行:

mf <- eval(temp, environment(formula$terms), parent.frame())
  • temp
    是未评估的模型框架调用,该包已根据其目的对其进行了修改:
stats::model.frame(formula = Surv(futime, death) ~ sex + age, 
    data = df, id = id, xlev = list(sex = c("F", "M")))
  • parent.frame()
    是调用当前函数的环境,即
    stats::model.frame()
    的环境(参见上面的调用堆栈)
  • environment(formula$terms)
    是创建公式的环境,通常是 R 假设它可以找到公式中引用的所有内容的环境(如果不在父框架中)

我还没有测试过,但添加了

assign("df", df, environment(my_formula))

你的功能可能会解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.