Обновление формулы внутри функции

Я пытаюсь написать функцию, которая будет соответствовать glm и вернуть мне некоторую статистику:

library(caret)
library(marginalmodelplots)
data(MissAmerica08)
MissUSA <- MissAmerica08[,c(2,4,6,7,8,10)]

glm.binomial<-function(data,formula,num.trials,linkf="logit",
                       trctr=trainControl(method = "none"),conf.lvl=0.95)
{
result<-list()
lhs<-formula[[2]]
data[,"wghts"]<-rep(num.trials,length(data[,as.character(lhs)])) 
data[,as.character(lhs)]<-data[,as.character(formula[[2]])]/num.trials #so the vector is in [0,1]
fit<-train(form=formula,data=data,family=binomial(),method="glm", 
       trControl=trainControl(method = "none"), weights=wghts)
result[["Statistics"]] <- summary(fit)
}
glm.binomial(formula=Top10~.,data=MissUSA,num.trials=9) 

Моя проблема в том, что, поскольку я помещаю wghts во фрейм данных при подгонке модели, вектор wghts также становится независимой переменной. Можно ли изменить формулу перед тем, как поместить ее в train (), чтобы в модели не было wghts? Или, в качестве альтернативы, я могу хранить wghts где-нибудь еще? Я также думал поставить if (формула [[3]] == '.') И заменить '.' Всеми другими факторами, однако я не уверен, как это сделать. Спасибо!


person Dean    schedule 18.09.2014    source источник


Ответы (2)


Я бы поставил логическую проверку и обновил формулу с помощью функции update. Например,

f1 <- y ~ a + b + w

myfun <- function(f, w) {
  if (is.vector(w)) {
    f <- update(f, ~ . - w)
  }
  return(f)
}

myfun(f = f1, w = 1:3)

[1] y ~ a + b
person Roman Luštrik    schedule 18.09.2014
comment
Спасибо за ваш комментарий. К сожалению, это не сработает, если справа у меня стоит '.' вместо факторов, сгруппированных вместе, и это моя настоящая проблема. Если у меня есть определенные факторы, включенные в формулу, моя функция работает нормально, однако, если '.' присутствует ломается. Как вы думаете, есть ли другой способ сохранить wghts во фрейме данных, не распознавая его как фактор? - person Dean; 19.09.2014

Я не уверен, что вам нужно что-то делать, кроме использования

glm.binomial(formula=Top10~.-wghts,data=MissUSA,num.trials=9) 

Ваш звонок в train включает указание weights=wghts. train использует "стандартное соглашение" терминов для создания матрицы проекта, и это делается независимо от получения вектора весов.

Если вам интересно, вот отрывок из-под капота train.formula:

<snip>
x <- model.matrix(Terms, m, contrasts, na.action = na.action)
cons <- attr(x, "contrast")
xint <- match("(Intercept)", colnames(x), nomatch = 0)
if (xint > 0) x <- x[, -xint, drop = FALSE]
y <- model.response(m)
w <- as.vector(model.weights(m)) 
res <- train(x, y, weights = w, ...)
<snip>

Объект x здесь будет содержать любую правую часть указанной формулы, и model.weights работает независимо от этого. (Кстати, я пытался разобраться во всем этом во время первых заявлений о S +, и мне хотелось бы, чтобы кто-нибудь проделал пошаговое руководство по этому коду, чтобы объяснить это тогда. Если это кажется волшебным и расплывчатым ... это так).

Вы должны протестировать приведенный выше код, чтобы убедиться, что он дает ожидаемый результат. Если это так, я сделаю запись на веб-сайте курсора для поезда, чтобы показать и пример с использованием сгруппированных биномиальных данных с glm и train.

Спасибо,

Максимум

person topepo    schedule 19.09.2014
comment
Спасибо за это понимание. Моя функция дает те же результаты, что и glm (), поэтому она работает нормально (ей нужно только result в последней строке, чтобы гарантировать, что результат будет напечатан, и trControl = trctr при вызове поезда). Моя идея заключалась в том, чтобы функция автоматически удаляла wghts вместо того, чтобы просить пользователя вручную вычесть их, однако я не смог изменить формулу и по-прежнему сделать ее узнаваемой с помощью train (). - person Dean; 19.09.2014