Как сделать регрессию sm.Logit на матрице patsy?

Я хотел создать логит-график для естественной кубической сплайн-функции с четырьмя степенями свободы для P (заработная плата > 250), но по какой-то причине возникает ошибка. Я не понимаю, почему, потому что OLS работает нормально.

Вот код (он должен быть полностью рабочим без каких-либо настроек, кроме, конечно, рассматриваемой части):

import pandas as pd
from patsy import dmatrix
import statsmodels.api as sm
import matplotlib.pyplot as plt
import numpy as np

plt.figure(figsize=(7,5))
df = pd.read_csv('http://web.stanford.edu/~oleg2/hse/wage/wage.csv').sort_values(by=['age'])
ind_df = df[['wage', 'age']].copy()

plt.xlabel('Age', fontsize=15)
plt.ylabel('Wage', fontsize=15)
plt.ylim((0,333))

d = 4
knots = [df.age.quantile(0.25), df.age.quantile(0.5), df.age.quantile(0.75)]

my_spline_transformation = f"bs(train, knots={knots}, degree={d}, include_intercept=True)"

transformed = dmatrix( my_spline_transformation, {"train": df.age}, return_type='dataframe' )

lft = sm.Logit( (df.age > 250), transformed )
y_grid1 = lft.predict(transformed)

plt.show()

Ошибка:

ValueError: shapes (3000,9) and (3000,9) not aligned: 9 (dim 1) != 3000 (dim 0)

Я попытался перенести фрейм данных, но в результате получились какие-то бредовые графики. Как мне это сделать правильно?


person user9102437    schedule 14.11.2020    source источник


Ответы (1)


Во-первых, ваша зависимая переменная неверна, она должна быть df.wage>250 вместо df.age>250 .

Во-вторых, я не уверен, что вам нужен сплайн с 4 степенями свободы (имеется в виду до полинома x^4) для одной переменной. Если вы посмотрите на свои данные, это не так сложно:

df = pd.read_csv('http://web.stanford.edu/~oleg2/hse/wage/wage.csv').sort_values(by=['age'])
df['wage_factor'] = (df.wage > 250).astype('int')
fig,ax = plt.subplots(1,2,figsize=(8,3))
df.plot.scatter(x='age',y='wage',ax=ax[0])
df.plot.scatter(x='age',y='wage_factor',ax=ax[1])

введите здесь описание изображения

В-третьих, после того, как вы вызовете sm.Logit(), вам нужно его подогнать. Смотрите ниже, как это должно быть:

d = 3
knots = [30,60]

my_spline_transformation = f"bs(train, knots={knots}, degree={d}, include_intercept=True)"
transformed = dmatrix( my_spline_transformation, {"train": df.age}, return_type='dataframe' )

lft = sm.Logit( (df.wage>250), transformed)
res = lft.fit()
y_grid1 = res.predict(transformed)

Эти будут работать без ошибок. Я не уверен, что результаты имеют смысл, потому что в этом примере ваши цели сильно несбалансированы, и логистическая регрессия будет довольно проблематичной.

person StupidWolf    schedule 15.11.2020