R回帰分析における「not defined because of singularities」問題の解決
数理統計学や数学を専攻しているなら、原因を大まかに把握して直面している問題を解決するだけでなく、数理的証明まで理解することを強く勧める。
エラー
診断
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.5723 0.1064 5.381 4.98e-05 ***
최고기온 -0.3528 0.1490 -2.368 0.030 *
최저기온 0.2982 0.1955 1.525 0.146
일교차 NA NA NA NA
Rで回帰分析を行う際に、回帰係数で not defined because of singularities
というメッセージが表示され、係数推定ができない問題。
原因
- デザインマトリックス $X$ がフルランクを持たず、最小二乗解を求める際に$X^{T} X$ の逆行列が存在しないため。このためエラーメッセージにも ‘singularities’ が言及されている。
- 簡単に言えば、多重共線性が存在するということ。
- さらに簡単に言えば、独立変数同士が独立していないということ。
$X^T X$ の逆行列が存在する必要十分条件: $m \ge n$ のとき、行列 $X \in \mathbb{R}^{m \times n}$ の逆行列が存在する必要十分条件は$X$ がフルランクを持つことである。 $$ \exists \left( X^{T} X \right)^{-1} \iff \text{rank} X = n $$
これは実際には教科書に載っている、初心者が犯すミスの一つで、例にあるように、ある程度頭を使って派生変数を作る際に初めて直面する問題だ。理由を聞くと数学的には非常に当然だが、数理統計の直感がようやく身についてくる学生には当然犯してしまうミス。
あなただけではなく、他の人たちも、私も経験した実際のミス。重要なのは、この問題を解決した後に、数学―特に行列代数や線形代数が重要であるという事実に共感し、徹底した理論学習の動機にすること。
典型的な状況として、次のような例を思い描くことができる。
> data = as.data.frame(matrix(runif(60),20,3))
> names(data) <- c("감기확률", "최고기온", "최저기온")
> lm(감기확률 ~ 최고기온 + 최저기온, data = data)
Call:
lm(formula = 감기확률 ~ 최고기온 + 최저기온, data = data)
Coefficients:
(Intercept) 최고기온 최저기온
0.5723 -0.3528 0.2982
例えば、風邪がかかる確率を説明するデータとして気温に関するデータがあるとする。
> data$일교차 <- (data$최고기온 - data$최저기온)
> out <- lm(감기확률 ~ 최고기온 + 최저기온 + 일교차, data = data)
しかし、常識として広く知られているように、風邪が流行する時期は単純に気温が低いことよりも、日較差が大きい時期と関連する。したがって、上記のように派生変数として日較差を追加すると、次の結果が得られる。
> summary(out)
Call:
lm(formula = 감기확률 ~ 최고기온 + 최저기온 + 일교차, data = data)
Residuals:
Min 1Q Median 3Q Max
-0.41562 -0.03316 0.00506 0.10834 0.35714
Coefficients: (1 not defined because of singularities)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.5723 0.1064 5.381 4.98e-05 ***
최고기온 -0.3528 0.1490 -2.368 0.030 *
최저기온 0.2982 0.1955 1.525 0.146
일교차 NA NA NA NA
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 0.1988 on 17 degrees of freedom
Multiple R-squared: 0.2779, Adjusted R-squared: 0.193
F-statistic: 3.271 on 2 and 17 DF, p-value: 0.06281
解決法
可能であれば新しい派生変数を除外し、どうしても残したい場合は、その派生変数を作る際に使用した元の独立変数を削除する必要がある。直感的に理解できるなら、非線形関数を適用するなど、派生変数の生成方法自体を変更することも可能。
コード
data = as.data.frame(matrix(runif(60),20,3))
names(data) <- c("감기확률", "최고기온", "최저기온")
lm(감기확률 ~ 최고기온 + 최저기온, data = data)
data$일교차 <- (data$최고기온 - data$최저기온)
out <- lm(감기확률 ~ 최고기온 + 최저기온 + 일교차, data = data)
summary(out)
環境
- OS: Windows 11
- julia: v4.1.1