Pregunta ¿Cómo puedo reemplazar un término en una fórmula R por dos?


Tengo algo a lo largo de las líneas de

y ~ x + z

Y me gustaría transformarlo en

y ~ x_part1 + x_part2 + z

En general, me gustaría tener una función que tome una fórmula y devuelva esa fórmula con todos los términos que coincidan con "^ x $" reemplazados por "x_part1" y "x_part2". Esta es mi solución actual, pero se siente tan tonta ...

my.formula <- fruit ~ apple + banana
var.to.replace <- 'apple'
my.terms <- labels(terms(my.formula))
new.terms <- paste0('(', 
                    paste0(var.to.replace, 
                           c('_part1', '_part2'),
                           collapse = '+'),
                    ')')
new.formula <- reformulate(termlabels = gsub(pattern = var.to.replace,
                                             replacement = new.terms,
                                             x = my.terms),                                 
                           response = my.formula[[2]])

Una advertencia adicional es que la fórmula de entrada se puede especificar con interacciones.

y ~ b*x + z

debería dar salida a una de estas fórmulas (equivalentes)

y ~ b*(x_part1 + x_part2) + z
y ~ b + (x_part1 + x_part2) + b:(x_part1 + x_part2) + z
y ~ b + x_part1 + x_part2 + b:x_part1 + b:x_part2 + z

Mr Flick ha abogado por el uso de

sustituto (y ~ b * x + z, lista (x = comilla (x_part1 + x_part2)))

pero cuando tengo almacenada la fórmula, quiero modificarla en una variable, como en

my.formula <- fruit ~ x + banana

Este enfoque parece requerir un poco más de masaje:

substitute(my.formula, list(x=quote(apple_part1 + apple_part2)))
# my.formula

El cambio necesario para ese enfoque fue:

do.call(what = 'substitute',
        args = list(apple, list(x=quote(x_part1 + x_part2))))

Pero no puedo averiguar cómo usar este enfoque cuando tanto 'x' como c ('x_part', 'x_part2') se almacenan en variables con nombres, por ejemplo. var.to.replace y new.terms encima.


5
2017-08-09 15:12


origen


Respuestas:


¿Qué hay de trabajar con la fórmula como una cadena? Muchos modelos base R como lm() acepta una fórmula de cadena (y siempre puedes usar formula() de otra manera). En este caso, puedes usar algo como gsub():

f1 <- "y ~ x + z"
f2 <- "y ~ b*x + z"

gsub("x", "(x_part1 + x_part2)", f1)
#> [1] "y ~ (x_part1 + x_part2) + z"

gsub("x", "(x_part1 + x_part2)", f2)
#> [1] "y ~ b*(x_part1 + x_part2) + z"

Por ejemplo, con mtcars conjunto de datos, y decir que queremos reemplazar mpg (x) con disp + hp (x_part1 + x_part2):

f1 <- "qsec ~ mpg + cyl"
f2 <- "qsec ~ wt*mpg + cyl"

f1 <- gsub("mpg", "(disp + hp)", f1)
f2 <- gsub("mpg", "(disp + hp)", f2)

lm(f1, data = mtcars)
#> 
#> Call:
#> lm(formula = f1, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)         disp           hp          cyl  
#>    22.04376      0.01017     -0.02074     -0.56571

lm(f2, data = mtcars)
#> 
#> Call:
#> lm(formula = f2, data = mtcars)
#> 
#> Coefficients:
#> (Intercept)           wt         disp           hp          cyl  
#>   20.421318     1.554904     0.026837    -0.056141    -0.876182  
#>     wt:disp        wt:hp  
#>   -0.006895     0.011126

0
2017-08-10 21:49



Puedes usar el substitute función para esto

substitute(y ~ b*x + z, list(x=quote(x_part1 + x_part2)))
# y ~ b * (x_part1 + x_part2) + z

Aquí usamos la lista nombrada para decirle a R que reemplace la variable x con la expresión x_part1 + x_part2


6
2017-08-09 18:06



Puede escribir una función recursiva para modificar el árbol de expresiones de la fórmula:

replace_term <- function(f, old, new){
  n <- length(f)
  if(n > 1) {
    for(i in 1:n) f[[i]] <- Recall(f[[i]], old, new)

    return(f)
  }

  if(f == old) new else f
}

Que puede utilizar para modificar, por ejemplo, las interacciones:

> replace_term(y~x*a+z - x, quote(x), quote(x1 + x2))
y ~ (x1 + x2) * a + z - (x1 + x2)

3
2017-08-09 17:22



Si solo desea modificar los efectos principales, puede restar x y agregar las dos nuevas variables.

> f <- y ~ x + z
> update(f, .~.-x+x_part1 + x_part2)
y ~ z + x_part1 + x_part2

1
2017-08-09 16:25