Я делаю множественную линейную регрессию с statsmodels.formula.api (версия 0.9.0) в Windows 10. После подбора модели и получения сводки со следующими строками я получаю сводку в формате сводного объекта.
X_opt = X[:, [0,1,2,3]]
regressor_OLS = sm.OLS(endog= y, exog= X_opt).fit()
regressor_OLS.summary()
OLS Regression Results
==============================================================================
Dep. Variable: y R-squared: 0.951
Model: OLS Adj. R-squared: 0.948
Method: Least Squares F-statistic: 296.0
Date: Wed, 08 Aug 2018 Prob (F-statistic): 4.53e-30
Time: 00:46:48 Log-Likelihood: -525.39
No. Observations: 50 AIC: 1059.
Df Residuals: 46 BIC: 1066.
Df Model: 3
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 5.012e+04 6572.353 7.626 0.000 3.69e+04 6.34e+04
x1 0.8057 0.045 17.846 0.000 0.715 0.897
x2 -0.0268 0.051 -0.526 0.602 -0.130 0.076
x3 0.0272 0.016 1.655 0.105 -0.006 0.060
==============================================================================
Omnibus: 14.838 Durbin-Watson: 1.282
Prob(Omnibus): 0.001 Jarque-Bera (JB): 21.442
Skew: -0.949 Prob(JB): 2.21e-05
Kurtosis: 5.586 Cond. No. 1.40e+06
==============================================================================
Я хочу выполнить обратное исключение для значений P для уровня значимости 0,05. Для этого мне нужно удалить предиктор с самыми высокими значениями P и снова запустить код.
Я хотел знать, есть ли способ извлечь значения P из итогового объекта, чтобы я мог запустить цикл с условным оператором и найти важные переменные, не повторяя шаги вручную.
Спасибо.






Сохраните подходящую модель как переменную results, например:
import statsmodels.api as sm
model = sm.OLS(y,x)
results = model.fit()
Затем создайте функцию, как показано ниже:
def results_summary_to_dataframe(results):
'''take the result of an statsmodel results table and transforms it into a dataframe'''
pvals = results.pvalues
coeff = results.params
conf_lower = results.conf_int()[0]
conf_higher = results.conf_int()[1]
results_df = pd.DataFrame({"pvals":pvals,
"coeff":coeff,
"conf_lower":conf_lower,
"conf_higher":conf_higher
})
#Reordering...
results_df = results_df[["coeff","pvals","conf_lower","conf_higher"]]
return results_df
Вы можете дополнительно изучить все атрибуты объекта results, используя dir () для печати, а затем добавить их в функцию и df соответственно.
Спасибо, Майкл Б., за помощь.
Нет проблем, если это сработало, отметьте ответ как правильный! Удачного кодирования / изучения данных !!
Ответ от @Michael B работает хорошо, но требует «воссоздания» таблицы. Сама таблица фактически доступна напрямую из атрибута summary (). Tables. Каждая таблица в этом атрибуте (который представляет собой список таблиц) представляет собой SimpleTable, у которого есть методы для вывода различных форматов. Затем мы можем прочитать любой из этих форматов обратно как pd.DataFrame:
import statsmodels.api as sm
model = sm.OLS(y,x)
results = model.fit()
results_summary = results.summary()
# Note that tables is a list. The table at index 1 is the "core" table. Additionally, read_html puts dfs in a list, so we want index 0
results_as_html = results_summary.tables[1].as_html()
pd.read_html(results_as_html, header=0, index_col=0)[0]
Это не работает при использовании API формул. AttributeError: 'OLSResults' object has no attribute 'tables'
На какой у вас версии? Я использую python 3.6.5 и использую последнюю версию statsmodels, но не тестировал более старые версии.
Python 3.6.5, statsmodels 0.9.0
Woops - забыл метод сводки! Спасибо что подметил это. Ответ обновлен.
Почему я не подумал об этом? Граница хакерская, но очень аккуратная. Вот альтернатива с использованием методов csv, если она пригодится: pd.read_csv(pd.compat.StringIO(table.as_csv()), index_col=0)
Простое решение - всего одна строка кода:
LRresult = (result.summary2().tables[1])
Как упоминал ZaxR в следующем комментарии, Summary2 еще не считается стабильным, но хорошо работает и с Summary. Так что это может быть правильный ответ:
LRresult = (result.summary().tables[1])
Это даст вам объект фрейма данных:
type(LRresult)
pandas.core.frame.DataFrame
Чтобы получить значимые переменные и снова запустить тест:
newlist = list(LRresult[LRresult['P>|z|']<=0.05].index)[1:]
myform1 = 'binary_Target' + ' ~ ' + ' + '.join(newlist)
M1_test2 = smf.logit(formula=myform1,data=myM1_1)
result2 = M1_test2.fit(maxiter=200)
LRresult2 = (result2.summary2().tables[1])
LRresult2
Summary2 еще не считается стабильным, хотя выглядит близким. См. это обсуждение.
Также работает для summary (). Это должен быть принятый ответ
Вы можете написать так, как показано ниже. Это будет легко исправить и каждый раз будет работать практически правильно.
lr.summary2()
Если вам нужна окружающая информация, попробуйте следующее:
import pandas as pd
dfs = {}
fs = fa_model.summary()
for item in fs.tables[0].data:
dfs[item[0].strip()] = item[1].strip()
dfs[item[2].strip()] = item[3].strip()
for item in fs.tables[2].data:
dfs[item[0].strip()] = item[1].strip()
dfs[item[2].strip()] = item[3].strip()
dfs = pd.Series(dfs)
Приведенный ниже код помещает все показатели в словарь, доступный по ключу.. Промежуточный результат - это на самом деле DataFrame, который вы можете использовать, я не вводил коэффициенты в dictionary, но вы можете применить аналогичный метод, но затем на два уровня глубины dict[var][metric].
Чтобы упростить ввод ключей, я преобразовал названия некоторых показателей в более удобные для ввода версии. Например. "Prob (Omnibus):" превращается в prob_omnibus, так что вы можете получить доступ к значению, res_dict ['prob_omnibus'].
import pandas as pd
res = sm.OLS(y, X).fit()
model_results_df = []
coefficient_df = None
for i, tab in enumerate(res.summary().tables):
header, index_col = None, None
if i == 1:
coefficient_df = pd.read_html(tab.as_html(), header=0, index_col=0)[0]
else:
df = pd.read_html(tab.as_html())[0]
model_results_df += [df.iloc[:,0:2], df.iloc[:,2:4]]
model_results_df = pd.DataFrame(np.concatenate(model_results_df), columns=['metric', 'value'])
model_results_df.dropna(inplace=True, axis=0)
model_results_df.metric = model_results_df.metric.apply(lambda x : x.lower().replace(' (', '_')
.replace('.', '').replace('(', '_')
.replace(')', '').replace('-', '_')
.replace(':', '').replace(' ', '_'))
res_dict = dict(zip(model_results_df.metric.values, model_results_df.value.values))
res_dict['f_statistic']
Я до сих пор не думаю, что существует четкий ответ, охватывающий весь запрос. Вот один из способов захватить все в двух фреймах данных (один для средней таблицы, один для показателей вверху и внизу).
def reform_df(dft):
# quick and dirty stacking of cols 2,3 on 0,1
dfl = dft[[0,1]]
dfr = dft[[2,3]]
dfr.columns = 0,1
dfout = pd.concat([dfl,dfr])
dfout.columns=['Parameter','Value']
return dfout
def model_summary_to_dataframe(model):
# first the middle table
results_df = pd.DataFrame(model.summary().tables[1])
results_df = results_df.set_index(0)
results_df.columns = results_df.iloc[0]
results_df = results_df.iloc[1:]
results_df.index.name='Parameter'
# now for the surrounding information
metrics_top = reform_df(pd.DataFrame(model.summary().tables[0]))
metrics_bot = reform_df(pd.DataFrame(model.summary().tables[2]))
metrics_df = pd.concat([metrics_top,metrics_bot])
return pd.DataFrame(results_df),metrics_df
В принятом ответе показано, как преобразовать сводную таблицу в pandas DataFrame. Однако для варианта использования выбора по p-значениям лучше напрямую использовать атрибут
results.pvalues, который также используется во втором ответе.