Диагностируйте
С сообщением об ошибке:
2 survfit(mod_init, newdata = base_case)
1 my_function(Surv(start, stop, event) ~ rx + number, data = bladder2)
проблема явно не с coxph
во время подгонки модели, но с survfit
.
И из этого сообщения:
10 eval(predvars, data, env)
9 model.frame.default(formula = Surv(start, stop, event) ~ rx +
number, data = data)
Я могу сказать, что проблема заключается в том, что во время ранней стадии survfit
, функция model.frame.default()
не может найти модели кадра, содержащий соответствующие данные, используемые в формуле Surv(start, stop, event) ~ rx + number
. Поэтому он жалуется.
Что такое рама модели?
модели кадр, формируются из data
аргумента, переданного фитинг рутины, как lm()
, glm()
и mgcv:::gam()
.Это кадр данных с тем же числом строк, как data
, но:
- сбросив все переменные не ссылаются
formula
- добавив множество атрибутов, наиболее важным из которых является
envrionement
Наиболее подпрограммы модели, такие как lm()
, glm()
и mgcv:::gam()
, по умолчанию сохраняют рамку модели в соответствующем объекте. Это имеет преимущество, что, если мы позже позвоним predict
, и не будет newdata
, он найдет данные из этого модельного кадра для оценки. Однако явным недостатком является то, что он существенно увеличит размер вашего приспособленного объекта.
Однако, исключение составляет survival:::coxph()
. Он по умолчанию не сохранит такую модельную рамку в установленном объекте. Ясно, что это делает результирующий приспособленный объект намного меньшим по размеру, но подвергает вас проблеме, с которой вы столкнулись. Если мы хотим задать survival:::coxph()
, чтобы сохранить эту модель, используйте model = TRUE
этой функции.
Тест с survial:::coxph()
library(survival); data(bladder)
my_function <- function(myformula, mydata, keep.mf = TRUE) {
fit <- coxph(myformula, mydata, method = "breslow", model = keep.mf)
survfit(fit)
}
Теперь этот вызов функции не получится, как вы уже видели:
my_function(Surv(start, stop, event) ~ rx + number, bladder2, keep.mf = FALSE)
, но этот вызов функции будет иметь успех:
my_function(Surv(start, stop, event) ~ rx + number, bladder2, keep.mf = TRUE)
То же поведение для lm()
Мы можем на самом деле демонстрируют такое же поведение в lm()
:
## generate some toy data
foo <- data.frame(x = seq(0, 1, length = 20), y = seq(0, 1, length = 20) + rnorm(20, 0, 0.15))
## a wrapper function
bar <- function(myformula, mydata, keep.mf = TRUE) {
fit <- lm(myformula, mydata, model = keep.mf)
predict.lm(fit)
}
Теперь это будет успех, сохраняя модель рамы:
bar(y ~ x - 1, foo, keep.mf = TRUE)
пока это не удастся, b у отбрасывания модель рамы:
bar(y ~ x - 1, foo, keep.mf = FALSE)
Использование аргумента newdata
?
Обратите внимание, что мой пример для lm()
немного искусственно, потому что мы можем фактически использовать newdata
аргумент в predict.lm()
, чтобы пройти через эту проблему:
bar1 <- function(myformula, mydata, keep.mf = TRUE) {
fit <- lm(myformula, mydata, model = keep.mf)
predict.lm(fit, newdata = lapply(mydata, mean))
}
Теперь держите ли мы модель кадр, как получится:
bar1(y ~ x - 1, foo, keep.mf = TRUE)
bar1(y ~ x - 1, foo, keep.mf = FALSE)
Тогда вы можете задаться вопросом: можем ли мы сделать то же самое для survfit()
?
survfit()
- общая функция, в вашем коде вы действительно звоните survfit.coxph()
. Для этой функции действительно есть аргумент newdata
. Документация гласит:
NewData:
фрейм данных с одинаковыми именами переменных, как те, которые появляются в «coxph» формулы . ... ... Значение по умолчанию - среднее значение ковариатов, используемых в соответствии с 'coxph'.
Итак, давайте попробуем:
my_function1 <- function(myformula, mydata) {
mtrace.off()
fit <- coxph(myformula, mydata, method = "breslow")
survival:::survfit.coxph(fit, newdata = lapply(mydata, mean))
}
, и мы надеемся, что эта работа:
my_function1(Surv(start, stop, event) ~ rx + number, bladder2)
Но:
Error in is.data.frame(data) (from #5) : object 'mydata' not found
1: my_function1(Surv(start, stop, event) ~ rx + number, bladder2)
2: #5: survival:::survfit.coxph(fit, lapply(mydata, mean))
3: stats::model.frame(object)
4: model.frame.coxph(object)
5: eval(temp, environment(formula$terms), parent.frame())
6: eval(expr, envir, enclos)
7: stats::model.frame(formula = Surv(start, stop, event) ~ rx + number, data =
8: model.frame.default(formula = Surv(start, stop, event) ~ rx + number, data
9: is.data.frame(data)
Обратите внимание, что хотя мы проходим в newdata
, то есть не используется при построении рамы модели:
3: stats::model.frame(object)
Только object
, копия подобранной модели, передается model.frame.default()
.
Это очень отличается от того, что происходит в predict.lm()
, predict.glm()
и mgcv:::predict.gam()
. В этих подпрограммах newdata
передается model.frame.default()
. Например, в lm()
, есть:
m <- model.frame(Terms, newdata, na.action = na.action, xlev = object$xlevels)
Я не использую survival
пакет, так что не знаю, как newdata
работы в этом пакете. Поэтому я думаю, что нам действительно нужен эксперт, объясняющий это.
Благодарим вас за очень четкое объяснение. Одна вещь беспокоит меня: почему это работает в интерактивном использовании (вне функции)? – Theodor