Прогнозирование приемлемости кредита: обработка данных-2

В последней части этой серии я показал основные операции обработки данных, которые включают в себя: удаление постоянных функций, удаление повторяющихся функций, удаление повторяющихся строк, удаление функций, связанных ›85% отсутствующих значений. Это предварительные шаги, которые нам нужно выполнить почти для каждого набора данных. После завершения описанной выше обработки мы сократили количество функций со 153 до 93. В этой части я рассмотрю каждую функцию вручную, обработаю их и удаляю ненужные функции.

В последней части мы сохранили все точки данных в одном фрейме данных «df». Начнем изучать форму данных.

df.shape
(457728, 93)

Мы видим, что теперь у нас есть 93 функции. Прежде чем мы исследуем каждую функцию, нам нужно создать функцию графика для визуализации. По этой ссылке я позаимствовал следующую функцию.

Вышеупомянутая функция принимает два параметра; первая - это имя функции, а вторая - логическая переменная: независимо от того, является ли функция непрерывной или категориальной. Если функция является непрерывной, то функция строит две подзаголовки: (1) распределение признака и (2) две коробчатые диаграммы на основе класса credit_status. С другой стороны, если признак является категориальным, то первый подзаголовок является графиком подсчета, а второй подзаголовок основан на классах group_by ссуды_статус.

Следующие коды в основном не требуют пояснений. Я иногда опускаю подробные пояснения.

Функции 0–10:

df.iloc[0:5, 0: 10]

Функция: сумма кредита

### Feature: loan_amnt
-------------------------------
len(df.loan_amnt.value_counts())
1415
plot_feature('loan_amnt', True)

Похоже, все кредиты не уникальны. Определенная сумма выпадает несколько раз. Это может быть причиной; у компании есть некоторый диапазон или определенная сумма для ссуды.

Функция: термин

### Feature: term
-------------------------------
df.term = df.term.str.replace('months', '').astype(np.int)
df.term.value_counts()
36    341042
60    116686
Name: term, dtype: int64
plot_feature('term', False)

Функция: процентная ставка

### Feature: int_rate
-------------------------------
df.int_rate = df.int_rate.str.replace('%', '').astype(np.float32)
len(df.int_rate.value_counts())
200
plot_feature('int_rate', True)

Похоже, что заявители, которые не могли позволить себе выплатить долг и в конечном итоге были списаны со счетов, должны были заплатить более высокую процентную ставку.

Характеристики: уклон и земляное полотно

Кажется, что grade и sub_grade имеют одинаковую форму и взаимосвязь со статусом ссуды. В этом случае я бы оставил sub_grade, потому что он несет больше информации, чем оценка.

Функция: должность

### Feature: emp_title
-------------------------------
len(df.emp_title.value_counts())
128310
It looks like emp_title has lots of unique value, which may not strongly be associated with predicted loan_status. Therefore, I delete the feature.
features_to_be_removed.extend(['emp_title', 'id'])

11–20 функций

df.iloc[0:5, 6: 20]

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

Feature: Home_ownership

Функция: статус подтверждения

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

Функция: Issue_d

### Feature: issue_d
### ------------------
df.issue_d.value_counts()
Oct-2014    33699
Jul-2014    25974
Jul-2015    23990
Jan-2015    22750
Oct-2015    22431
Nov-2014    21186
Apr-2015    20097
Dec-2015    19106
May-2015    17964
Aug-2015    17492
Apr-2014    17140
May-2014    17133
Aug-2014    16780
Nov-2015    16540
Jun-2015    15304
Jun-2014    15207
Mar-2015    14997
Mar-2014    14988
Feb-2015    14464
Jan-2014    14464
Feb-2014    13945
Sep-2015    13838
Sep-2014     9344
Dec-2014     8283
Jan-2017     5912
Mar-2017     5008
Feb-2017     4241
May-2017     3644
Apr-2017     3431
Jun-2017     2849
Jul-2017     2366
Aug-2017     1863
Sep-2017     1298
Name: issue_d, dtype: int64

Функция «Issue_d» - это строка. Поскольку мы имеем дело с данными за три года и сохраняем независимость нашей модели от года, я извлекаю только месяц, а затем конвертирую их в категории.

df['issue_month'] = pd.Series(df.issue_d).str.replace(r'-\d+', '')
plot_feature('issue_month', False)

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

df.issue_month = df.issue_month.astype("category", categories=np.unique(df.issue_month)).cat.codes
df.issue_month.value_counts()
10    56130
5     52330
4     43126
0     40668
8     38741
9     37726
1     36135
7     34993
6     33360
3     32650
2     27389
11    24480
Name: issue_month, dtype: int64
df['issue_year'] = pd.Series(df.issue_d).str.replace(r'\w+-', '').astype(np.int)
df.issue_year.value_counts()
2015    218973
2014    208143
2017     30612
Name: issue_year, dtype: int64

Поскольку URL-адрес не имеет ничего общего с кредитным_статусом, я просто удаляю его.

Функция: цель

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

Поскольку заголовок и почтовый индекс имеют много уникальных значений, я просто удаляю их из пространства функций.

Функция: состояние адреса

Функция addr_state имеет пятьдесят уникальных значений, поскольку существует пятьдесят состояний. Если мы посмотрим на график ниже, то увидим, что кандидаты из одних штатов заплатили больше, чем другие. Следовательно, эта особенность может быть дискриминационной.

21–30 функций

31–40 функций

df.iloc[0:5, 25: 40]

41–50 функций

df.iloc[0:5, 35: 50]

51–60 функций

61–70 функций

71–80 функций

81–90 функций

91 остальные функции

df.iloc[0:5, 85:]

Удаленные функции

Проверив каждую функцию вручную, я обнаружил, что 61 неуместная. Давайте посмотрим, какие функции выбраны для удаления.

len(set(features_to_be_removed))
61
print(features_to_be_removed)
['emp_title', 'id', 'url', 'title', 'zip_code', 'issue_d', 'mths_since_last_delinq', 'mths_since_last_record', 'inq_last_6mths', 'mths_since_last_delinq', 'mths_since_last_record', 'total_pymnt', 'total_pymnt_inv', 'total_rec_prncp', 'total_rec_int', 'total_rec_late_fee', 'recoveries', 'collection_recovery_fee', 'last_pymnt_d', 'last_pymnt_amnt', 'last_credit_pull_d', 'last_fico_range_high', 'last_fico_range_low', 'collections_12_mths_ex_med', 'mths_since_last_major_derog', 'acc_now_delinq', 'tot_coll_amt', 'tot_cur_bal', 'total_rev_hi_lim', 'avg_cur_bal', 'bc_open_to_buy', 'bc_util', 'chargeoff_within_12_mths', 'delinq_amnt', 'mo_sin_old_il_acct', 'mo_sin_old_rev_tl_op', 'mo_sin_rcnt_rev_tl_op', 'mo_sin_rcnt_tl', 'mths_since_recent_bc', 'mths_since_recent_bc_dlq', 'mths_since_recent_inq', 'mths_since_recent_revol_delinq', 'num_accts_ever_120_pd', 'num_actv_bc_tl', 'num_actv_rev_tl', 'num_bc_sats', 'num_bc_tl', 'num_il_tl', 'num_op_rev_tl', 'num_rev_accts', 'num_rev_tl_bal_gt_0', 'num_sats', 'num_tl_120dpd_2m', 'num_tl_30dpd', 'num_tl_90g_dpd_24m', 'num_tl_op_past_12m', 'pct_tl_nvr_dlq', 'percent_bc_gt_75', 'tot_hi_cred_lim', 'total_bal_ex_mort', 'total_bc_limit', 'debt_settlement_flag', 'total_il_high_credit_limit']

И, наконец, я отказался от всех вышеперечисленных функций:

df_selected = df.drop(list(set(features_to_be_removed)), axis = 1)
df_selected.shape
(457728, 36)

В приведенном выше коде мы видим, что есть 36 финальных функций, готовых для создания модели прогнозирования кредита. Давайте также проверим, есть ли какие-либо пропущенные значения в любой из выбранных 36 функций.

Если вы запустите приведенный выше код, вы увидите, что «dti» и «revol_util» имеют 21 и 223 пропущенных значения. Я использую метод panda dropna (), чтобы удалить примеры, связанные с отсутствующими значениями.

Кодирование функции

Пришло время закодировать некоторые категориальные особенности. В следующем коде я закодировал «цель», «домовладение», «степень», «под_граду», «addr_state»:

Хорошо, давайте сохраним окончательный набор данных с выбранными функциями.

df_selected.to_csv('./data/df_selected.csv', index = False)

В следующей части серии я проведу предварительный анализ. Если возможно, сделайте некоторую разработку функций. А пока, если у вас есть какие-либо вопросы по этой части, пожалуйста, напишите комментарий ниже или вы можете связаться со мной:

Email: [email protected]
LinkedIn: https://www.linkedin.com/in/sabber-ahamed/
Github: https://github.com/msahamed
Medium: https://medium.com/@sabber/