2017-04-12 81 views
3

假設我有一個pandas數據幀:如何獲取statsmodels/patsy公式所依賴的列?

df = pd.DataFrame({'x1': [0, 1, 2, 3, 4], 
        'x2': [10, 9, 8, 7, 6], 
        'x3': [.1, .1, .2, 4, 8], 
        'y': [17, 18, 19, 20, 21]}) 

現在我適合使用公式(使用patsy引擎蓋下)一個statsmodels模式:

import statsmodels.formula.api as smf 
fit = smf.ols(formula='y ~ x1:x2', data=df).fit() 

我要的是列的列表dffit依賴於,以便我可以在另一個數據集上使用fit.predict()。如果我嘗試list(fit.params.index),例如,我得到:

['Intercept', 'x1:x2'] 

我試圖重現帕齊設計矩陣,並使用design_info,但我仍然只能永遠得到x1:x2。我要的是:

['x1', 'x2'] 

甚至:

['Intercept', 'x1', 'x2'] 

我怎樣才能得到這正好從fit對象?

+0

爲什麼不把'':'x1:x2'分開到'':'',然後,如果你只是在交互'x1'和'x2'?就像'fit.model.formula.split(':')',然後適當地過濾掉其餘部分。地獄,正則表達式分裂會更好,處理'+',''''等。 – blacksite

+0

@bwk你有沒有在這個問題上取得任何進展?看看我的答案,它應該適合你的需求。 –

回答

3

簡單的測試,如果列名出現在公式的字符串表示:

ols = smf.ols(formula='y ~ x1:x2', data=df) 
fit = ols.fit() 

print([c for c in df.columns if c in ols.formula]) 
['x1', 'x2', 'y'] 

有通過重構帕齊模式(更詳細,但也更可靠)的另一種方法,它不依賴於原始數據幀:

md = patsy.ModelDesc.from_formula(ols.formula) 
termlist = md.rhs_termlist + md.lhs_termlist 

factors = [] 
for term in termlist: 
    for factor in term.factors: 
     factors.append(factor.name()) 

print(factors) 
['x1', 'x2', 'y'] 
+0

謝謝,這就是我一直在尋找的! – bwk

+0

如果碰巧有一個列名稱是公式的子字符串,則這不起作用。例如,我有一個名爲'rt'的列,它被公式'C(other_col,Helmert)' – sammosummo

+0

@sammosummo捕獲。事實上,我在答案中提到的第一種方法將匹配任何子字符串。但是,第二種方法不執行此字符串匹配。 –

0

predict採用相同結構的數據幀或字典,並且呼叫patsy以兼容的方式轉換它。複製此還可以檢查該代碼在statsmodels.base.model.Results.predict其中的核心是

exog = dmatrix(self.model.data.design_info.builder, 
          exog, return_type="dataframe") 

本身被存儲在terms的描述中design_info的公式的信息。變量名稱本身在summary()中使用,並作爲返回的熊貓系列中的索引使用,例如results.params

+0

獲取公式不是問題。 'summary()'中的變量名稱不是DataFrame中的原始變量,而是_transformed_變量名稱;即分別有「x1:x2」而不是「x1」和「x2」。 – bwk