使用 R 風格公式擬合模型¶
自 0.5.0 版以來,statsmodels
允許使用者使用 R 風格的公式來擬合統計模型。在內部,statsmodels
使用 patsy 套件將公式和資料轉換為模型擬合中使用的矩陣。公式框架非常強大;本教學僅觸及表面。公式語言的完整描述可以在 patsy
文件中找到。
載入模組和函數¶
In [1]: import statsmodels.api as sm
In [2]: import statsmodels.formula.api as smf
In [3]: import numpy as np
In [4]: import pandas
請注意,除了常用的 statsmodels.api
之外,我們還呼叫了 statsmodels.formula.api
。事實上,這裡的 statsmodels.api
僅用於載入資料集。formula.api
包含了許多與 api
中相同的功能(例如 OLS、GLM),但它也包含了大多數這些模型的小寫版本。一般來說,小寫模型接受 formula
和 df
參數,而大寫模型則採用 endog
和 exog
設計矩陣。formula
接受一個字串,該字串以 patsy
公式描述模型。df
接受 pandas 資料框。
dir(smf)
將列印可用模型的列表。
相容於公式的模型具有以下通用呼叫簽章: (formula, data, subset=None, *args, **kwargs)
使用公式的 OLS 迴歸¶
首先,我們擬合 入門指南 頁面上描述的線性模型。下載資料、子集列,並進行列表式刪除以移除遺失的觀測值
In [5]: df = sm.datasets.get_rdataset("Guerry", "HistData").data
In [6]: df = df[['Lottery', 'Literacy', 'Wealth', 'Region']].dropna()
In [7]: df.head()
Out[7]:
Lottery Literacy Wealth Region
0 41 37 73 E
1 38 51 22 N
2 66 13 61 C
3 80 46 76 E
4 79 69 83 E
擬合模型
In [8]: mod = smf.ols(formula='Lottery ~ Literacy + Wealth + Region', data=df)
In [9]: res = mod.fit()
In [10]: print(res.summary())
OLS Regression Results
==============================================================================
Dep. Variable: Lottery R-squared: 0.338
Model: OLS Adj. R-squared: 0.287
Method: Least Squares F-statistic: 6.636
Date: Thu, 03 Oct 2024 Prob (F-statistic): 1.07e-05
Time: 16:08:49 Log-Likelihood: -375.30
No. Observations: 85 AIC: 764.6
Df Residuals: 78 BIC: 781.7
Df Model: 6
Covariance Type: nonrobust
===============================================================================
coef std err t P>|t| [0.025 0.975]
-------------------------------------------------------------------------------
Intercept 38.6517 9.456 4.087 0.000 19.826 57.478
Region[T.E] -15.4278 9.727 -1.586 0.117 -34.793 3.938
Region[T.N] -10.0170 9.260 -1.082 0.283 -28.453 8.419
Region[T.S] -4.5483 7.279 -0.625 0.534 -19.039 9.943
Region[T.W] -10.0913 7.196 -1.402 0.165 -24.418 4.235
Literacy -0.1858 0.210 -0.886 0.378 -0.603 0.232
Wealth 0.4515 0.103 4.390 0.000 0.247 0.656
==============================================================================
Omnibus: 3.049 Durbin-Watson: 1.785
Prob(Omnibus): 0.218 Jarque-Bera (JB): 2.694
Skew: -0.340 Prob(JB): 0.260
Kurtosis: 2.454 Cond. No. 371.
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
類別變數¶
查看上面列印的摘要,請注意 patsy
確定 *Region* 的元素是文字字串,因此它將 *Region* 視為類別變數。patsy
的預設值也包含截距,因此我們自動刪除了其中一個 *Region* 類別。
如果 *Region* 是一個我們想明確地視為類別的整數變數,我們可以使用 C()
運算符來做到這一點
In [11]: res = smf.ols(formula='Lottery ~ Literacy + Wealth + C(Region)', data=df).fit()
In [12]: print(res.params)
Intercept 38.651655
C(Region)[T.E] -15.427785
C(Region)[T.N] -10.016961
C(Region)[T.S] -4.548257
C(Region)[T.W] -10.091276
Literacy -0.185819
Wealth 0.451475
dtype: float64
可以在這裡找到更多關於 patsy
的類別變數函數的高級功能範例: Patsy:類別變數的對比編碼系統
運算符¶
我們已經看到「~」將模型的左側與右側分隔開來,而「+」將新列添加到設計矩陣中。
移除變數¶
「-」號可用於移除列/變數。例如,我們可以從模型中移除截距,方法是
In [13]: res = smf.ols(formula='Lottery ~ Literacy + Wealth + C(Region) -1 ', data=df).fit()
In [14]: print(res.params)
C(Region)[C] 38.651655
C(Region)[E] 23.223870
C(Region)[N] 28.634694
C(Region)[S] 34.103399
C(Region)[W] 28.560379
Literacy -0.185819
Wealth 0.451475
dtype: float64
乘法交互作用¶
「:」會將一個新列添加到設計矩陣中,該列包含其他兩列的乘積。「*」也將包括相乘的個別列
In [15]: res1 = smf.ols(formula='Lottery ~ Literacy : Wealth - 1', data=df).fit()
In [16]: res2 = smf.ols(formula='Lottery ~ Literacy * Wealth - 1', data=df).fit()
In [17]: print(res1.params)
Literacy:Wealth 0.018176
dtype: float64
In [18]: print(res2.params)
Literacy 0.427386
Wealth 1.080987
Literacy:Wealth -0.013609
dtype: float64
運算符還有許多其他可能用法。請查閱 patsy 文件以了解更多資訊。
函數¶
您可以將向量化函數套用到模型中的變數
In [19]: res = smf.ols(formula='Lottery ~ np.log(Literacy)', data=df).fit()
In [20]: print(res.params)
Intercept 115.609119
np.log(Literacy) -20.393959
dtype: float64
定義一個自訂函數
In [21]: def log_plus_1(x):
....: return np.log(x) + 1.0
....:
In [22]: res = smf.ols(formula='Lottery ~ log_plus_1(Literacy)', data=df).fit()
In [23]: print(res.params)
Intercept 136.003079
log_plus_1(Literacy) -20.393959
dtype: float64
命名空間¶
請注意,以上所有範例都使用呼叫命名空間來尋找要套用的函數。使用的命名空間可以透過 eval_env
關鍵字來控制。例如,您可能想使用 patsy:patsy.EvalEnvironment
提供自訂命名空間,或者您可能想使用「乾淨」的命名空間,我們可以透過傳遞 eval_func=-1
來提供。預設是使用呼叫者的命名空間。如果有人在使用者命名空間或傳遞給 patsy
的資料結構中有一個名為 C
的變數,並且 C
用於公式中處理類別變數,則這可能會產生(不)預期的後果。請參閱 Patsy API 參考以了解更多資訊。
在尚不(尚未)支援公式的模型中使用公式¶
即使給定的 statsmodels
函數不支援公式,您仍然可以使用 patsy
的公式語言來產生設計矩陣。然後,這些矩陣可以作為 endog
和 exog
參數饋送至擬合函數。
若要產生 numpy
陣列
In [24]: import patsy
In [25]: f = 'Lottery ~ Literacy * Wealth'
In [26]: y, X = patsy.dmatrices(f, df, return_type='matrix')
In [27]: print(y[:5])
[[41.]
[38.]
[66.]
[80.]
[79.]]
In [28]: print(X[:5])
[[ 1. 37. 73. 2701.]
[ 1. 51. 22. 1122.]
[ 1. 13. 61. 793.]
[ 1. 46. 76. 3496.]
[ 1. 69. 83. 5727.]]
y
和 X
將會是 patsy.DesignMatrix
的實例,它是 numpy.ndarray
的子類別。
若要產生 pandas 資料框
In [29]: f = 'Lottery ~ Literacy * Wealth'
In [30]: y, X = patsy.dmatrices(f, df, return_type='dataframe')
In [31]: print(y[:5])
Lottery
0 41.0
1 38.0
2 66.0
3 80.0
4 79.0
In [32]: print(X[:5])
Intercept Literacy Wealth Literacy:Wealth
0 1.0 37.0 73.0 2701.0
1 1.0 51.0 22.0 1122.0
2 1.0 13.0 61.0 793.0
3 1.0 46.0 76.0 3496.0
4 1.0 69.0 83.0 5727.0
In [33]: print(sm.OLS(y, X).fit().summary())
OLS Regression Results
==============================================================================
Dep. Variable: Lottery R-squared: 0.309
Model: OLS Adj. R-squared: 0.283
Method: Least Squares F-statistic: 12.06
Date: Thu, 03 Oct 2024 Prob (F-statistic): 1.32e-06
Time: 16:08:49 Log-Likelihood: -377.13
No. Observations: 85 AIC: 762.3
Df Residuals: 81 BIC: 772.0
Df Model: 3
Covariance Type: nonrobust
===================================================================================
coef std err t P>|t| [0.025 0.975]
-----------------------------------------------------------------------------------
Intercept 38.6348 15.825 2.441 0.017 7.149 70.121
Literacy -0.3522 0.334 -1.056 0.294 -1.016 0.312
Wealth 0.4364 0.283 1.544 0.126 -0.126 0.999
Literacy:Wealth -0.0005 0.006 -0.085 0.933 -0.013 0.012
==============================================================================
Omnibus: 4.447 Durbin-Watson: 1.953
Prob(Omnibus): 0.108 Jarque-Bera (JB): 3.228
Skew: -0.332 Prob(JB): 0.199
Kurtosis: 2.314 Cond. No. 1.40e+04
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.4e+04. This might indicate that there are
strong multicollinearity or other numerical problems.