2012-04-14 2 views
5

Я хотел бы передать правую часть формулы функции R, которая затем «добавляет» левую часть формулы и вызывает gam(). Я хотел бы достичь этого без уродливых конструкций asforma() и т. Д.Как передать правую часть формулы другой формуле?

Я застрял в следующем минимальном примере, знаете ли вы, что пошло не так?

require(mgcv) 
set.seed(0) ## set.seed(1) 
gamEx1 <- gamSim(1, n=400, dist="normal", scale=2) ## simulate some data 
str(gamEx1) ## display structure 

## calling gam() and passing the right-hand side of a formula 
gamFitter <- function(formula.RHS, data, ...){ 
    z <- 2*data$y + data$f0 # some given values 
    gam(z ~ formula.RHS, data=data, ...) # call gam() 
} 

## call the function with the right-hand side of a formula 
gamFitter(formula.RHS=~s(x0)+s(x1)+s(x2)+s(x3), data=gamEx1) 

Error in model.frame.default(formula = z ~ formula.RHS, data = data, 
          drop.unused.levels = TRUE) : 
    invalid type (language) for variable 'formula.RHS' 

ответ

12

кажется что вы должны использовать встроенные функции R, na Мели update.formula, нет необходимости, чтобы написать новую функцию:

> form <- ~s(x0)+s(x1)+s(x2)+s(x3) 
> form 
~s(x0)+s(x1)+s(x2)+s(x3) 
> update.formula(form, z ~ .) 
z ~ s(x0) + s(x1) + s(x2) + s(x3) 
+0

Спасибо, Дерек, я не знал, что эта функция существует. –

+0

@MariusHofert Мне кажется, этот ответ более изящный, чем принятый в настоящее время. Не могли бы вы пересмотреть принятие? – Andrie

4

запутано, но это работает:

form1 <- as.formula("hi ~ lo + mid") 
form2 <- as.formula("blue ~ red + green") 
form2[[3]] <- form1[[3]] 
> form2 
blue ~ lo + mid 
+0

Ну, как я уже писал, я * не * хочу использовать 'as.formula()' и строки, это просто плохая практика. Спасибо, в любом случае. –

+0

@MariusHofert - можете ли вы объяснить, что такое плохая практика о 'as.formula()'? – Chase

+0

Формула - это формула - и ее следует рассматривать как таковую. Преобразование его в/обращение с ним по строкам - это плохая практика. Обратите внимание, что рекомендуемый подход к построению функций с формулами рассматривается здесь: http://developer.r-project.org/model-fitting-functions.txt Два хороших примера, которые * не * включают строки (и, следовательно, не требуют 'as.formula()') - это функции 'lm()' и '(mgcv: :) gam'. –

5

Вот версия опираясь на идеи @ GSK3 в:

changeLHS <- function(formula, lhs) { 
    if (length(formula) == 2) { 
    formula[[3]] <- formula[[2]] 
    } 
    formula[[2]] <- substitute(lhs) 
    formula 
} 

changeLHS(a~b+c, z+w) # z + w ~ b + c 
changeLHS(~b+c, z+w) # z + w ~ b + c 

Итак, ваш код становится:

gamFitter <- function(formula.RHS, data, ...){ 
    frm <- changeLHS(formula.RHS, 2*y + f0) 
    gam(frm, data=data, ...) # call gam() 
} 
+0

* Ницца *, спасибо. Я думаю, что 'rhs' должен быть' lhs' в 'changeLHS', чтобы сделать его более понятным, но он определенно работает хорошо. –

+0

@MariusHofert - Хорошо, я изменил его. Теперь «правая сторона» оставлена, верно? ;-) – Tommy

0

Опираясь на другие ответы, если вам нужно заменить LHS programmatically by passing strings (а-ля reformulate), то два маленьких ухищрений может помочь.

Использование @ подхода Томми:

changeLHS <- function(formula, lhs) { 
    if (length(formula) == 2) { 
     formula[[3]] <- formula[[2]] 
    } 
    formula[[2]] <- as.symbol(lhs) 
    formula 
} 

form <- ~s(x0)+s(x1)+s(x2)+s(x3) 
changeLHS(form, "z") 
## z ~ s(x0) + s(x1) + s(x2) + s(x3) 

Использование @ подход Дерека:

update(form, reformulate(".", "z")) 
## z ~ s(x0) + s(x1) + s(x2) + s(x3) 
Смежные вопросы