如何使用update在公式右侧添加前缀?

3

假设我有一个 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一起使用)。如果我使用lapplyupdate,就可以在结尾添加| 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

有人知道为什么会出现这种情况,或者如何修复它(当然,除了逐个修复每个模型之外)吗?
2个回答

3
关于主要问题:如何设置公式
我建议先添加两个额外的截距部分,然后重新排列右侧:
f <- y ~ x2
ff <- update(Formula(f), . ~ . | 1 | 1)
formula(ff, rhs = c(2, 1, 3))
## y ~ 1 | x2 | 1

关于这个问题:为什么更新只在第一部分中使用"."起作用?

您预期此代码将返回相同的结果:

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

感谢你们两位展示了这个应该如何工作,还解释了其中的原理! - Jake Fisher

1

个人而言,当我遇到简单的问题时,我总是利用字符串。以下是基础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一样在内部将任何公式字符串转换为公式类型),则您甚至不需要上面lapply中的as.formula部分。


@AchimZeileis 我在输入时想到了 library(Formula),但还是谢谢你的提醒。 - LyzandeR
Formula包已经被精心设计,以避免字符串处理的问题。在这种特殊情况下,通过术语标签可能是可以接受的。但是你很容易就会遇到字符串处理容易出错的情况,尤其是在恢复公式部分的时候。例如,在“y ~ x1 | factor(z1 | z2)”中,你需要注意正确处理第二个“|”。而且,术语标签总是扩展紧凑的交互符号表示法(例如,“a * b”将变成“a + b + a:b”)等。 - Achim Zeileis
@AchimZeileis 对于所有的事情,你需要知道如何使用工具。构建统计软件包时,使用字符串是没有意义的,但对于交互式使用或直接的过程通常是可以的。 - LyzandeR
1
当然了。如果您相当清楚输入的结构,那么使用您的建议通常是可以的。但是,我想指出,在某些情况下,字符串路线可能会导致问题。我们在各种包(包括我们自己的!)中都遇到过这种情况,这也是编写“Formula”包以解决此问题的动机之一。 - Achim Zeileis
@AchimZeileis 感谢您的评论:)。我相信您在构建专业软件包时一定遇到了一些问题。我承认我还没有探索过 Formula 软件包,但是在阅读了您的评论后,我会这样做,因为您的观点是正确的,我应该扩展自己在这方面的知识。谢谢! - LyzandeR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接