Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add a prefix to the right hand side of a Formula using update?

Tags:

r

formula

Say I have a list of Formula's:

library(Formula)
models <- list(y ~ x1, y ~ x2, y ~ x3)
models <- lapply(models, as.Formula)

And say I want to update them to be y ~ 1 | x1 | 1, y ~ 1 | x2 | 1, and y ~ 1 | x3 | 1 (for example, to work with mnlogit). If I use update with lapply, I can add the | 1 to the end:

lapply(models, update, . ~ . | 1)  # Works as expected
# [[1]]
# y ~ x1 | 1
# 
# [[2]]
# y ~ x2 | 1
#
# [[3]]
# y ~ x3 | 1

But I can't add the 1 | to the beginning:

lapply(models, update, . ~ 1 | . | 1)  # Fails -- why is the dot not replaced?
# [[1]]
# y ~ 1 | . | 1
#
# [[2]]
# y ~ 1 | . | 1
#
# [[3]]
# y ~ 1 | . | 1

Does anyone know why this is, or how to fix it (other than fixing each of the models one by one, of course)?

like image 494
Jake Fisher Avatar asked Dec 03 '25 02:12

Jake Fisher


2 Answers

As for the main question: How can you set up the formulas?

I would recommend to first add the two additional intercept parts and then re-order the right-hand side:

f <- y ~ x2
ff <- update(Formula(f), . ~ . | 1 | 1)
formula(ff, rhs = c(2, 1, 3))
## y ~ 1 | x2 | 1

And then concerning: Why does the update only work with the . in the first part?

You expected that this code returns the same result:

f <- y ~ x2
update(Formula(f), . ~ 1 | . | 1)
## y ~ 1 | . | 1

But clearly it doesn't. The reason is simple: The update() method cycles through all left-hand and right-hand parts. Here, the first right-hand part x2 gets updated with 1. The second right-hand part is empty (f only has one right-hand side) and hence gets updated to .. Analogously, for the third part.

If there is exactly one right-hand side in the original formula, one could have implemented your approach. But with several parts this would have been a mess. E.g.,

update(Formula(y ~ x1 | x2 | x3), . ~ . + z1 | 1 | . - x3)
## y ~ x1 + z1 | 1 | 1
like image 190
Achim Zeileis Avatar answered Dec 05 '25 16:12

Achim Zeileis


Personally I always take advantage of strings when I face a simple problem. This is in base-R:

lapply(models, function(x) {
  as.formula(paste( 'y ~ 1 | ', labels(terms(x)) , '| 1')))
}

And output is:

[[1]]
y ~ 1 | x1 | 1
<environment: 0x000000000a475128>

[[2]]
y ~ 1 | x2 | 1
<environment: 0x00000000003ea848>

[[3]]
y ~ 1 | x3 | 1
<environment: 0x000000000a94e100>

All of them formulas as you need them.

If mnlogit accepts strings in the formula argument (i.e. converts any formula strings to formula type internally like lm does) then you don't even need the as.formula bit in the above lapply.

like image 35
LyzandeR Avatar answered Dec 05 '25 17:12

LyzandeR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!