如何使用更新将前缀添加到公式的右侧?

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

假设我有一个 Formula 的列表:

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

并说我想将它们更新为 y ~ 1 | x1 | 1y ~ 1 | x2 | 1y ~ 1 | x3 | 1(例如,使用 mnlogit)。如果我将 updatelapply 一起使用,我可以将 | 1 添加到末尾:

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

但是我无法在开头添加 1 |:

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

有谁知道这是为什么,或者如何修复它(当然,除了一个一个地修复每个模型)?

就个人而言,当我遇到一个简单的问题时,我总是利用字符串。这是在 base-R 中:

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

输出为:

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

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

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

你需要的所有公式。

如果 mnlogit 接受公式参数中的字符串(即像 lm 那样在内部将任何公式字符串转换为公式类型),那么您甚至不需要 as.formula 位以上 lapply.

至于主要问题:如何设置公式

我建议先添加两个额外的拦截部分,然后重新排序右侧:

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

然后是关于:为什么更新只适用于 .在第一部分?

您期望此代码 returns 相同的结果:

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

但显然不是。原因很简单:update() 方法循环遍历所有左手和右手部分。此处,第一个右侧部分 x2 更新为 1。第二个右侧部分是空的(f 只有一个右侧)因此更新为 .。同理,对于第三部分。

如果原始公式中恰好有一个右侧,则可以实现您的方法。但是对于几个部分,这将是一团糟。例如,

update(Formula(y ~ x1 | x2 | x3), . ~ . + z1 | 1 | . - x3)
## y ~ x1 + z1 | 1 | 1