使用model.matrix进行一位有效编码

5

我对model.matrix中的一个问题不太理解。当我输入一个没有截距的单个二进制变量时,它返回两个级别。

> temp.data <- data.frame('x' = sample(c('A', 'B'), 1000, replace = TRUE))
> temp.data.table <- model.matrix( ~ 0 + x, data = temp.data)
> head(temp.data.table)
  xA xB
1  1  0
2  0  1
3  0  1
4  0  1
5  1  0
6  0  1

然而,当我进入另一个二进制级别时,它只创建了3列。为什么会这样呢?是什么导致函数的行为突然不同?我应该如何避免这种情况?

> temp.data <- data.frame('x' = sample(c('A', 'B'), 1000, replace = TRUE),
+                         'y' = sample(c('J', 'D'), 1000, replace = TRUE))
> temp.data.table <- model.matrix( ~ 0 + x + y, data = temp.data)
> head(temp.data.table)
  xA xB yJ
1  0  1  0
2  0  1  1
3  0  1  1
4  0  1  0
5  1  0  1
6  0  1  0
2个回答

6
你需要使用factors并将contrasts设置为FALSE。试试这个:
n <- 10
temp.data <- data.frame('x'=sample(c('A', 'B'), n, replace=TRUE),
                        'y'=factor(sample(c('J', 'D'), n, replace=TRUE)))
model.matrix( ~ 0 + x + y, data=temp.data,
              contrasts=list(y=contrasts(temp.data$y, contrasts=FALSE)))

#    xA xB yD yJ
# 1   0  1  1  0
# 2   1  0  0  1
# 3   0  1  1  0
# 4   1  0  0  1
# 5   0  1  0  1
# 6   1  0  1  0
# 7   1  0  1  0
# 8   0  1  1  0
# 9   0  1  0  1
# 10  0  1  1  0
# attr(,"assign")
# [1] 1 1 2 2
# attr(,"contrasts")
# attr(,"contrasts")$x
# [1] "contr.treatment"
# 
# attr(,"contrasts")$y
#   D J
# D 1 0
# J 0 1

为了理解这种情况发生的原因,请尝试:

contrasts(temp.data$y)
#   J
# D 0
# J 1

contrasts(temp.data$y, contrasts=F)
#   D J
# D 1 0
# J 0 1

当使用x变量时,通过设置0 +来自动完成拦截的移除。(实际上x也应该编码为factor)。

原因是,在线性回归中,通常将因子变量的级别与参考级别进行比较(可以使用relevel更改)。在您的模型矩阵中,使用0 +会从第一个变量中删除拦截,但不会从以下变量中删除拦截(尝试model.matrix(~0+y+x,data=temp.data),其中只有一个x而是). 这是使用默认情况下的处理对比确定的。

您可能想阅读一篇相关文章,详细解释了这个问题:


为什么会发生这种情况?我理解将具有k个级别的因子编码为k-1列的想法。但如果是这样,为什么不对每个因子都这样做呢?如果我们删除截距,为什么它不能将每个因子映射到级别数量上。我在逻辑方面遇到了困难。 - Kozolovska
谢谢,我不确定你是否有答案,但为什么它被设置为以那种特定的方式行为?(使用一个没有截距的分类变量与使用两个分类变量之间的差异)。 - Kozolovska
1
@Kozolovska,“为什么”是一个哲学问题 :) 但这是最常见的需求,因此也是最普遍的。我在我的答案中添加了一些关于逻辑的解释。 - jay.sf
1
非常感谢您的帮助。我现在或多或少明白了,我认为这是model.matrix的一种奇怪行为,因为我认为如果我不想要一个截距,那么所有的因子都不应该有一个。 - Kozolovska
我认为这种行为的原因是确保设计矩阵是满秩的(当输入变量也是线性无关的时候)。由于model.matrix旨在构建线性模型的设计矩阵,这作为默认行为是有道理的。 - jackkamm

1
你需要重置因子变量的对比度。请参见此帖子
temp.data <- data.frame('x' = sample(c('A', 'B'), 1000, replace = TRUE),
+                         'y' = sample(c('J', 'D'), 1000, replace = TRUE))

dat = model.matrix(~ -1 +., data=temp.data, contrasts.arg = lapply(temp.data[,1:2], contrasts, contrasts=FALSE))
head(dat)

  xA xB yD yJ
1  0  1  0  1
2  1  0  0  1
3  1  0  0  1
4  1  0  0  1
5  0  1  1  0
6  0  1  0  1

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