我想制作一个没有截距系数的简单线性模型(lm()
),因此我将-1
放在我的模型公式中,如下例所示。问题是summary(myModel)
的R平方回报似乎被高估了。 lm()
,summary()
和-1
是R中非常经典的功能/功能。因此我有点惊讶,我想知道这是一个错误还是有任何原因行为。
以下是一个例子:
x <- rnorm(1000, 3, 1)
mydf <- data.frame(x=x, y=1+x+rnorm(1000, 0, 1))
plot(y ~ x, mydf, xlim=c(-2, 10), ylim=c(-2, 10))
mylm1 <- lm(y ~ x, mydf)
mylm2 <- lm(y ~ x - 1, mydf)
abline(mylm1, col="blue") ; abline(mylm2, col="red")
abline(h=0, lty=2) ; abline(v=0, lty=2)
r2.1 <- 1 - var(residuals(mylm1))/var(mydf$y)
r2.2 <- 1 - var(residuals(mylm2))/var(mydf$y)
r2 <- c(paste0("Intercept - r2: ", format(summary(mylm1)$r.squared, digits=4)),
paste0("Intercept - manual r2: ", format(r2.1, digits=4)),
paste0("No intercept - r2: ", format(summary(mylm2)$r.squared, digits=4)),
paste0("No intercept - manual r2: ", format(r2.2, digits=4)))
legend('bottomright', legend=r2, col=c(4,4,2,2), lty=1, cex=0.6)
答案 0 :(得分:4)
哦,是的,我也陷入了这个陷阱!非常好的问题!!这是因为
和
mylm1
),y̅是平均值(y i ) - 这就是你所期望的,这就是SS tot 你基本上想要适当的R 2 代码:
attach(mylm1) # in general be careful with attach, here only for code clarity
y_fit <- mylm1$fitted.values
SSE <- sum((y_fit - y)^2)
SST <- sum((y - mean(y))^2)
1-SSE/SST # R^2 with intercept
y_fit2 <- mylm2$fitted.values
SSE2 <- sum((y_fit2 - y)^2) # SSE2 only slightly higher than SSE..
SST2 <- sum((y - 0)^2) # !!! the key difference is here !!!
1-SSE2/SST2 # R^2 without intercept
注意:我不清楚为什么在没有截距的模型中y̅是0而不是y(sub ),但它就是这样的。我自己通过调查和黑客上面的代码找到了困难的方法..
答案 1 :(得分:2)
你的公式错了。以下是我在计算摘要时在RcppArmadillo fastLm.R
中所做的事情:
## cf src/library/stats/R/lm.R and case with no weights and an intercept
f <- object$fitted.values
r <- object$residuals
mss <- if (object$intercept) sum((f - mean(f))^2) else sum(f^2)
rss <- sum(r^2)
r.squared <- mss/(mss + rss)
df.int <- if (object$intercept) 1L else 0L
n <- length(f)
rdf <- object$df
adj.r.squared <- 1 - (1 - r.squared) * ((n - df.int)/rdf)
有两个地方你需要跟踪是否有拦截。