12

我正在尝试创建解决方案的更简洁版本,这需要以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,但名称更难直接解释(特别是在我们注意给出描述性名称的真实数据中d1d2与这个通用示例相反):

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*在公式中遇到它时如何准确解释,以便我可以做出我想要的细微调整。

4

1 回答 1

11

在这种情况下,您不需要定义新运算符:在公式中d1/d2扩展为d1 + d1:d2. 换句话说d1/d2,指定d2嵌套在d1. 继续你的例子:

out3 <- lm(y ~ cut(v2,breaks=c(0,.25,.8,1))/I(v1 < .3))
all.equal(coef(out1), coef(out3))
# [1] TRUE

进一步的评论

因素可能是交叉的或嵌套的。如果可以观察到两个因素水平的每个组合,例如性别和治疗、温度和 pH 值等,则两个因素是交叉的。如果该因素的每个水平只能在一个水平内观察到,则该因素嵌套在另一个内其他因素,例如城镇和国家,员工和商店等。

这些关系反映在模型的参数化中。对于交叉因子,我们使用d1*d2d1 + d2 + d1:d2来给出每个因子的主效应以及交互作用。对于嵌套因子,我们使用d1/d2或为每个级别d1 + d1:d2的形式提供一个单独的子模型。1 + d2d1

嵌套的想法不限于因素,例如,我们可以sex/x用来拟合男性和女性的单独线性回归x

在公式中,%in%等价于:,但它可用于强调数据/模型的嵌套或层次结构。例如,a + b %in% a与 相同a + a:b,但将其解读为“a 中的 a 加 b”可以更好地描述所拟合的模型。即便如此,使用/在强调结构的同时也具有简化模型公式的优点。

于 2015-09-20T18:29:17.940 回答