我正在尝试创建此解决方案的更简洁版本,这需要以d1 + d1:d2
.
鉴于*
在公式的上下文中是完整交互的简洁替代(即d1 * d2
给出d1 + d2 + d1:d2
),我的方法是尝试定义替代运算符,例如%+:%
使用我在其他应用程序中习惯的中缀方法,a拉:
"%+:%" <- function(d1,d2) d1 + d2 + d1:d2
然而,这可以预见地失败了,因为我没有仔细评估;让我们介绍一个例子来说明我的进步:
set.seed(1029)
v1 <- runif(1000)
v2 <- runif(1000)
y <- .8*(v1 < .3) + .2 * (v2 > .25 & v2 < .8) -
.4 * (v2 > .8) + .1 * (v1 > .3 & v2 > .8)
通过这个例子,希望可以清楚为什么简单地写出这两个术语可能是不可取的:
y ~ cut(v2, breaks = c(0, .25, .8, 1)) +
cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3)
一种接近我想要的输出的解决方法是将整个公式定义为一个函数:
plus.times <- function(outvar, d1, d2){
as.formula(paste0(quote(outvar), "~", quote(d1),
"+", quote(d1), ":", quote(d2)))
}
这给出了传递给 时的预期系数lm
,但名称更难直接解释(特别是在我们注意给出描述性名称的真实数据中d1
,d2
与这个通用示例相反):
out1 <- lm(y ~ cut(v2, breaks = c(0, .25, .8, 1)) +
cut(v2, breaks = c(0, .25, .8, 1)):I(v1 < .3))
out2 <- lm(plus.times(y, cut(v2, breaks = c(0, .25, .8, 1)), I(v1 < .3)))
any(out1$coefficients != out2$coefficients)
# [1] FALSE
names(out2$coefficients)
# [1] "(Intercept)" "d1(0.25,0.8]" "d1(0.8,1]" "d1(0,0.25]:d2TRUE"
# [5] "d1(0.25,0.8]:d2TRUE" "d1(0.8,1]:d2TRUE"
所以这不是最优的。
有没有办法定义调整代码,以便我上面提到的中缀运算符按预期工作?如何改变形式plus.times
以便不重命名变量?
我一直在四处寻找(?formula
, ?"~"
, ?":"
, getAnywhere(formula.default)
,这个答案等),但还没有看到 R*
在公式中遇到它时如何准确解释,以便我可以做出我想要的细微调整。