在lm公式中删除变量仍会触发对比错误。

9

我正在尝试在数据的一个子集上运行lm(),但遇到了问题。

dt = data.table(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100), x3 = as.factor(c(rep('men',50), rep('women',50)))) # sample data

lm( y ~ ., dt) # Use all x: Works
lm( y ~ ., dt[x3 == 'men']) # Use all x, limit to men: doesn't work (as expected)

上述方法不可行,因为数据集只包含男性,我们无法将性别变量x3包含在模型中。但是...
lm( y ~ . -x3, dt[x3 == 'men']) # Exclude x3, limit to men: STILL doesn't work
lm( y ~ x1 + x2, dt[x3 == 'men']) # Exclude x3, with different notation: works great

这是公式中“减号”符号的问题吗?请给予建议。注意:我当然可以用其他方式完成;例如,在将变量放入lm()之前,我可以排除它们。但我正在教授这个知识点,我不想让学生感到困惑,因为我已经告诉他们他们可以使用公式中的减号符号来排除变量。


3
有趣的是,model.matrix(y ~ . - x3, data = dt[x3 == "men"])model.matrix(y ~ x1 + x2, data = dt[x3 == "men"]) 都能运作(lm 在内部调用 model.matrix)。两种模型矩阵唯一的区别是一个包含 "contrasts" 属性(仍然包含 x3),并在后续的 lm 过程中被使用,可能导致您看到的错误。因此,我认为问题与 model.matrix 在删除项时创建和存储设计矩阵的方式有关。 - Maurits Evers
我试图通过使用 terms(y ~ . -x3, data=dt, simplify=TRUE) 来“展开” . 来获取一个简化公式,但是奇怪的是它仍然在变量属性中保留了 x3,这会使 lm 函数出错。 - MrFlick
1
@MrFlick - 看起来未在R中实现的 neg.out= 选项可能与此有关。从实施了 neg.out=terms 的 S 帮助文件中: 标志控制输入带 "-" 符号的术语的处理方式。如果为TRUE,则将检查术语以进行取消,否则将被忽略。如果为FALSE,则将保留负术语(具有负顺序)。 - thelatemail
1
@MauritsEvers:lm在修改过的数据上调用model.matrix。一开始,lm会组合并评估以下表达式:mf <- stats::model.frame( y ~ . -x3, dt[x3=="men"], drop.unused.levels=TRUE )。这会导致x3成为单级别因子。然后在mf上调用model.matrix(),而不是原始数据,从而导致我们观察到的错误。 - Artem Sokolov
@ArtemSokolov 但是公式中的“-x3”应该将“x3”从数据框中排除,因此它是否为单层并不重要。为什么它没有被排除? - robertspierre
1个回答

2
你遇到的错误是因为x3在模型中只有一个值="men"(请参见@Artem Sokolov下面的评论)
解决方法之一是提前进行子集处理:
dt = data.table(y = rnorm(100), x1 = rnorm(100), x2 = rnorm(100), x3 = as.factor(c(rep('men',50), rep('women',50)))) # sample data

dmen<-dt[x3 == 'men'] # create a new subsetted dataset with just men

lm( y ~ ., dmen[,-"x3"]) # now drop the x3 column from the dataset (just for the model)

或者你可以在同一个步骤中完成两个操作:

lm( y ~ ., dt[x3 == 'men',-"x3"])

总的来说,这是一个不错的解决方案。需要纠正的一件事是,在公式中的“-x3”并不会使“lm”认为您正在尝试减去该列。正确传达了“不要在模型中使用x3”的意图,但问题在于“lm”调用了“model.frame(...,drop.unused.levels = TRUE)”,导致“x3”成为单级因子,在“model.matrix()”中产生下游问题。 - Artem Sokolov
感谢Artem Sokolov的澄清,我已经从我的回答中删除了那个错误的解释。 - Dylan_Gomes

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