Statsmodels:计算拟合值和R方
我正在进行回归分析,代码如下(df
是一个 pandas
数据框):
import statsmodels.api as sm
est = sm.OLS(df['p'], df[['e', 'varA', 'meanM', 'varM', 'covAM']]).fit()
est.summary()
这个分析给了我一个 R-squared 值为 0.942
。接下来,我想把原始的 y-values
和拟合值画出来。为此,我对原始值进行了排序:
orig = df['p'].values
fitted = est.fittedvalues.values
args = np.argsort(orig)
import matplotlib.pyplot as plt
plt.plot(orig[args], 'bo')
plt.plot(orig[args]-resid[args], 'ro')
plt.show()
但是,这样得到的图表显示的值完全不对,根本没有任何迹象表明 R-squared 会是 0.9
。所以,我尝试自己手动计算一下:
yBar = df['p'].mean()
SSTot = df['p'].apply(lambda x: (x-yBar)**2).sum()
SSReg = ((est.fittedvalues - yBar)**2).sum()
1 - SSReg/SSTot
Out[79]: 0.2618159806908984
我是不是做错了什么?或者说有什么原因导致我计算的结果和 statsmodels 得到的结果差距这么大?SSTot
和 SSReg
的值分别是 48084
和 35495
。
2 个回答
5
如果你的模型是:
a = <yourmodel>.fit()
那么,要计算拟合值(也就是模型预测的结果):
a.fittedvalues
并且要计算R平方值(用来衡量模型的好坏):
a.rsquared
13
如果你在模型中不加入一个常数项(也就是一个固定的解释变量),statsmodels会根据未中心化的总平方和来计算R平方值,也就是说:
tss = (ys ** 2).sum() # un-centred total sum of squares
与之相对的是
tss = ((ys - ys.mean())**2).sum() # centred total sum of squares
因此,R平方值会高很多。
从数学上来说,这样做是正确的。因为,R平方值应该表示完整模型与简化模型相比,解释了多少变化。如果你把模型定义为:
ys = beta1 . xs + beta0 + noise
那么简化模型可以是:ys = beta0 + noise
,其中beta0
的估计值是样本的平均值,因此我们有:noise = ys - ys.mean()
。这就是在有常数项的模型中,为什么会有去均值的过程。
但是对于像这样的模型:
ys = beta . xs + noise
你可能只能简化为:ys = noise
。因为noise
被假设为零均值,所以你不能对ys
进行去均值处理。因此,在简化模型中,未解释的变化就是未中心化的总平方和。
这方面的详细信息可以在这里找到,查看rsquared
项。将yBar
设置为零,我预计你会得到相同的结果。