2012-04-14 13 views
5

Me gustaría pasar el lado derecho de una fórmula a una función R que luego "agrega" el lado izquierdo de la fórmula y llama al gam(). Me gustaría lograr esto sin construcciones feas como .formula() etc.¿Cómo pasar el lado derecho de una fórmula a otra fórmula?

Me quedé atrapado en el siguiente ejemplo mínimo, ¿sabes qué salió mal?

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' 

Respuesta

12

Parece que debe usar la funcionalidad incorporada de R, na Mely update.formula, no hay necesidad de escribir una nueva función:

> 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

Gracias, Derek, no sabía que esta función existe. –

+0

@MariusHofert Me parece que esta respuesta es más elegante que la actualmente aceptada. ¿Podrías reconsiderar el aceptar? – Andrie

4

kludgy pero funciona:

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

Bueno, como he escrito, I * no * que desee usar 'as.formula()' y cuerdas, es simplemente una mala práctica. Gracias de cualquier manera. –

+0

@MariusHofert - ¿puedes explicar qué es una mala práctica sobre 'as.formula()'? – Chase

+0

Una fórmula es una fórmula, y debe tratarse como tal. Convertirlo/tratarlo a través de cadenas es una mala práctica. Tenga en cuenta que el enfoque recomendado para construir funciones con fórmulas se trata aquí: http://developer.r-project.org/model-fitting-functions.txt Dos buenos ejemplos que * no * implican cadenas (y por lo tanto no requieren 'as.formula()') son las funciones 'lm()' y '(mgcv: :) gam'. –

5

Esto es un edificio versión sobre la idea de @ 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 

Por lo tanto, el código se convierte en:

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

* Agradable *, gracias. Supongo que 'rhs' debería ser' lhs' en 'changeLHS' para dejarlo más claro, pero definitivamente funciona bien. –

+0

@MariusHofert - Buen punto, lo cambié. Ahora el "lado derecho" queda, ¿verdad? ;-) – Tommy

0

Sobre la base de las otras respuestas, si es necesario sustituir LHS programmatically by passing strings (a la reformulate), a continuación, dos pequeños ajustes pueden ayudar.

Utilizando el enfoque de Tommy @:

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) 

Usando @ enfoque de Derek:

update(form, reformulate(".", "z")) 
## z ~ s(x0) + s(x1) + s(x2) + s(x3) 
Cuestiones relacionadas