Преобразование сводного объекта statsmodels в Pandas Dataframe

Я делаю множественную линейную регрессию с 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 из итогового объекта, чтобы я мог запустить цикл с условным оператором и найти важные переменные, не повторяя шаги вручную.

Спасибо.

В принятом ответе показано, как преобразовать сводную таблицу в pandas DataFrame. Однако для варианта использования выбора по p-значениям лучше напрямую использовать атрибут results.pvalues, который также используется во втором ответе.

Josef 10.10.2019 14:55
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
22
1
27 337
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Сохраните подходящую модель как переменную 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 соответственно.

Спасибо, Майкл Б., за помощь.

Sagun Kayastha 08.08.2018 23:12

Нет проблем, если это сработало, отметьте ответ как правильный! Удачного кодирования / изучения данных !!

Michael B 11.08.2018 03:07
Ответ принят как подходящий

Ответ от @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'

Jan Kislinger 29.10.2018 10:04

На какой у вас версии? Я использую python 3.6.5 и использую последнюю версию statsmodels, но не тестировал более старые версии.

ZaxR 30.10.2018 15:04

Python 3.6.5, statsmodels 0.9.0

Jan Kislinger 30.10.2018 16:23

Woops - забыл метод сводки! Спасибо что подметил это. Ответ обновлен.

ZaxR 30.10.2018 17:21

Почему я не подумал об этом? Граница хакерская, но очень аккуратная. Вот альтернатива с использованием методов csv, если она пригодится: pd.read_csv(pd.compat.StringIO(table.as_csv()), index_col=0)

Denziloe 25.06.2019 14:28

Простое решение - всего одна строка кода:

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 еще не считается стабильным, хотя выглядит близким. См. это обсуждение.

ZaxR 19.12.2018 06:58

Также работает для summary (). Это должен быть принятый ответ

user3357177 06.06.2020 03:02

Вы можете написать так, как показано ниже. Это будет легко исправить и каждый раз будет работать практически правильно.

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

Другие вопросы по теме