Исправьте ошибку среды "Survivation" ("Ошибка в is.data.frame"), используя pryr или другие инструменты Tidyverse.

Я изо всех сил пытаюсь найти элегантное решение для проблемы окружающей среды, с которой я постоянно сталкиваюсь, используя библиотеку выживания в R. Вот забавный пример проблемы, с которой я столкнулся:

# Make a fake data set
set.seed(1)
BigData <- cbind(rexp(100, .3), rbinom(100, 1, .7), 
             matrix(rnorm(300), ncol = 3)) %>% data.frame
names(BigData) <- c('time','event', 'var1', 'var2', 'var3')

# Make n function for fitting the model (myFitFunction).
# I am allowed to edit this function.
myFitFunction <- function(origdata, formula, ...){
  fit <- coxph(formula, data = origdata, ...)
  return(fit)
}
# There exists a function for fitting the 
# same model with new data (otherFitFunction).
# For the purposes of this example, say I cannot edit this one.
otherFitFunction <- function(object, newdata){
  survfit(object, newdata=newdata)
}
myMod <- myFitFunction(BigData[1:75,], 
        as.formula(Surv(time, event) ~ var1+var2+var3))
otherFitFunction(myMod, BigData[76:100,])

Это дает мне сообщение об ошибке:

"Ошибка в is.data.frame(data): объект" origdata "не найден. Вызовы: otherFitFunction ... -> model.frame.default -> is.data.frame"

Я знаю, что это распространенная проблема, особенно при выполнении перекрестной проверки, и есть некоторые решения, такие как: R: ошибка в is.data.frame(data): объект '' не найден, C5.0 сюжет. (Более конкретно, я знаю, что проблема в этом примере связана с кодом stats::model.frame() в строке ~55 в файле "fitfit.coxph.R"из пакета выживания.) Читая другие сообщения на stackexchange, я нашли решение моей проблемы, которая состоит в том, чтобы настроить myFitFunction() для:

myFitFunction <- function(origdata, formula, ...){
  myenv$origdata <- origdata
  fit <- coxph(formula, data = origdata, ...)
  environment(fit$formula) <- myenv
  fit$terms <- terms(fit$formula)

  return(fit)
}

Тем не менее, весь код, который я видел или использовал, кажется очень хакерским (включая мой, который требует от меня сохранения оригинальных данных каждый раз). Кроме того, в моем реальном коде я не могу на самом деле редактировать otherFitFunction() и могу только редактировать или даже напрямую обращаться к myFitFunction(), что ограничивает мою способность использовать некоторые решения, которые использовали другие.

Мне интересно, есть ли более элегантное решение этой проблемы. Я пытался поиграть с пакетом pryr, но, похоже, не могу найти ничего, что работает.

Любая помощь приветствуется.

1 ответ

Как насчет

myFitFunction <- function(origdata, formula, ...){
  environment(formula) <- environment()
  fit <- coxph(formula, data = origdata, ...)
  return(fit)
}

Поскольку формулы могут захватывать среды, вам просто нужно захватить среду, в которой origdata определено.

Альтернативой является адаптация к вызову в myFitFunction запустить все в родительском фрейме, используя исходные переменные. Например

myFitFunction <- function(origdata, formula, ...){
  call <- match.call()
  call$formula <- formula
  call$data <- call$origdata
  call$origdata <- NULL
  call[[1]] <- quote(coxph)
  fit <- eval.parent(call)
  return(fit)
}
Другие вопросы по тегам