Como escribe Roland se reduce a la definición de $R^2$ en los modelos con y sin intercepción. Más concretamente, la diferencia radica en el cálculo de la suma media de los cuadrados.
Podemos inspeccionar el código para summary()
simplemente escribiendo summary.lm
(sin ()
). Aquí están las partes relevantes:
> summary.lm
function (object, correlation = FALSE, symbolic.cor = FALSE,
...)
{
z <- object
...
r <- z$residuals
f <- z$fitted.values
...
mss <- if (attr(z$terms, "intercept"))
sum((f - mean(f))^2)
else sum(f^2)
rss <- sum(r^2)
...
ans <- z[c("call", "terms", if (!is.null(z$weights)) "weights")]
...
ans$r.squared <- mss/(mss + rss)
ans
}
El punto crucial es la distinción en attr(z$terms, "intercept"))
que se evalúa en 1
(convertido a TRUE
) en su primer modelo, pero 0
(o FALSE
) en el segundo. En el primer caso, mss
se calcula como la suma de las diferencias al cuadrado entre los ajustes y la media global, y en el segundo caso, es sólo la suma de los valores ajustados al cuadrado. De este modo, obtenemos valores diferentes para mss
. El resto del cálculo es idéntico.
Podemos calcular un ejemplo y reconstruir las diferentes $R^2$ s a mano:
> nn <- 10
> set.seed(1)
>
> X <- rnorm(nn)
> b <- X > 0
> y <- rep(0, nn)
> y[b == TRUE] <- 1
> y <- y + rnorm(nn)
>
> model0 <- lm(y ~ b)
> model1 <- lm(y ~ b - 1)
>
> mss0 <- sum((model0$fitted.values-mean(model0$fitted.values))^2)
> mss1 <- sum(model0$fitted.values^2)
> rss0 <- sum(model0$residuals^2)
> rss1 <- sum(model1$residuals^2)
> mss0/(mss0 + rss0)
[1] 0.1350045
> (rsq0 <- summary(model0)$r.squared)
[1] 0.1350045
> mss1/(mss1 + rss1)
[1] 0.4628321
> (rsq1 <- summary(model1)$r.squared)
[1] 0.4628321