這部分主要對kaggle的比賽Home Credit Default Risk做的一些探索性數(shù)據(jù)分析(EDA)
讀入數(shù)據(jù)
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
application_train = pd.read_csv('application_train.csv')
application_test = pd.read_csv('application_test.csv')
bureau = pd.read_csv('bureau.csv')
bureau_balance = pd.read_csv('bureau_balance.csv')
credit_card_balance = pd.read_csv('credit_card_balance.csv')
installments_payments = pd.read_csv('installments_payments.csv')
previous_application = pd.read_csv('previous_application.csv')
POS_CASH_balance = pd.read_csv('POS_CASH_balance.csv')
print('application_train.shape:', application_train.shape)
print('application_test.shape:', application_test.shape)
print('bureau.shape:', bureau.shape)
print('bureau_balance.shape:', bureau_balance.shape)
print('credit_card_balance.shape:', credit_card_balance.shape)
print('installments_payments.shape:', installments_payments.shape)
print('POS_CASH_balance.shape:', POS_CASH_balance.shape)
application_train.shape: (307511, 122)
application_test.shape: (48744, 121)
bureau.shape: (1716428, 17)
bureau_balance.shape: (27299925, 3)
credit_card_balance.shape: (3840312, 23)
installments_payments.shape: (13605401, 8)
POS_CASH_balance.shape: (10001358, 8)
查看數(shù)據(jù)
查看缺失的數(shù)據(jù)
def missing_data(data):
total = data.isnull().sum().sort_values(ascending=False)
percent = (data.isnull().sum()/data.isnull().count()).sort_values(ascending=False)
return pd.concat([total, percent], axis=1, keys=['total', 'percent'])
print('missing_data(application_train).head(10):')
print(missing_data(application_train).head(10))
missing_data(application_train).head(10):
total percent
COMMONAREA_MEDI 214865 0.698723
COMMONAREA_AVG 214865 0.698723
COMMONAREA_MODE 214865 0.698723
NONLIVINGAPARTMENTS_MODE 213514 0.694330
NONLIVINGAPARTMENTS_MEDI 213514 0.694330
NONLIVINGAPARTMENTS_AVG 213514 0.694330
FONDKAPREMONT_MODE 210295 0.683862
LIVINGAPARTMENTS_MEDI 210199 0.683550
LIVINGAPARTMENTS_MODE 210199 0.683550
LIVINGAPARTMENTS_AVG 210199 0.683550
print('missing_data(application_test).head(10):')
print(missing_data(application_test).head(10))
missing_data(application_test).head(10):
total percent
COMMONAREA_MEDI 33495 0.687161
COMMONAREA_AVG 33495 0.687161
COMMONAREA_MODE 33495 0.687161
NONLIVINGAPARTMENTS_MODE 33347 0.684125
NONLIVINGAPARTMENTS_MEDI 33347 0.684125
NONLIVINGAPARTMENTS_AVG 33347 0.684125
FONDKAPREMONT_MODE 32797 0.672842
LIVINGAPARTMENTS_AVG 32780 0.672493
LIVINGAPARTMENTS_MEDI 32780 0.672493
LIVINGAPARTMENTS_MODE 32780 0.672493
print('missing_data(bureau).head(10):')
print(missing_data(bureau).head(10))
missing_data(bureau).head(10):
total percent
AMT_ANNUITY 1226791 0.714735
AMT_CREDIT_MAX_OVERDUE 1124488 0.655133
DAYS_ENDDATE_FACT 633653 0.369170
AMT_CREDIT_SUM_LIMIT 591780 0.344774
AMT_CREDIT_SUM_DEBT 257669 0.150119
DAYS_CREDIT_ENDDATE 105553 0.061496
AMT_CREDIT_SUM 13 0.000008
CREDIT_TYPE 0 0.000000
AMT_CREDIT_SUM_OVERDUE 0 0.000000
CNT_CREDIT_PROLONG 0 0.000000
print('missing_data(bureau_balance).head(10):')
print(missing_data(bureau_balance).head(10))
missing_data(bureau_balance).head(10):
total percent
STATUS 0 0.0
MONTHS_BALANCE 0 0.0
SK_ID_BUREAU 0 0.0
print('missing_data(credit_card_balance).head(10):')
print(missing_data(credit_card_balance).head(10))
missing_data(credit_card_balance).head(10):
total percent
AMT_PAYMENT_CURRENT 767988 0.199981
AMT_DRAWINGS_OTHER_CURRENT 749816 0.195249
CNT_DRAWINGS_POS_CURRENT 749816 0.195249
CNT_DRAWINGS_OTHER_CURRENT 749816 0.195249
CNT_DRAWINGS_ATM_CURRENT 749816 0.195249
AMT_DRAWINGS_ATM_CURRENT 749816 0.195249
AMT_DRAWINGS_POS_CURRENT 749816 0.195249
CNT_INSTALMENT_MATURE_CUM 305236 0.079482
AMT_INST_MIN_REGULARITY 305236 0.079482
SK_DPD_DEF 0 0.000000
print('missing_data(installments_payments).head(10):')
print(missing_data(installments_payments).head(10))
missing_data(installments_payments).head(10):
total percent
AMT_PAYMENT 2905 0.000214
DAYS_ENTRY_PAYMENT 2905 0.000214
AMT_INSTALMENT 0 0.000000
DAYS_INSTALMENT 0 0.000000
NUM_INSTALMENT_NUMBER 0 0.000000
NUM_INSTALMENT_VERSION 0 0.000000
SK_ID_CURR 0 0.000000
SK_ID_PREV 0 0.000000
print('missing_data(POS_CASH_balance).head(10):')
print(missing_data(POS_CASH_balance).head(10))
missing_data(POS_CASH_balance).head(10):
total percent
CNT_INSTALMENT_FUTURE 26087 0.002608
CNT_INSTALMENT 26071 0.002607
SK_DPD_DEF 0 0.000000
SK_DPD 0 0.000000
NAME_CONTRACT_STATUS 0 0.000000
MONTHS_BALANCE 0 0.000000
SK_ID_CURR 0 0.000000
SK_ID_PREV 0 0.000000
檢查TARGET列的分布
print(application_train['TARGET'].value_counts())
application_train['TARGET'].astype(int).plot.hist()
plt.show()
數(shù)據(jù)分析
貸款的類型
讓我們看看貸款的類型雷客,以及在另一個的圖表上基协,TARGET目標(biāo)值為1(貸款未按時償還)的貸款的百分比(按貸款類型劃分)堡赔。
def plot_stats(feature, label_rotation=False, horizontal_layout=True):
temp = application_train[feature].value_counts()
df1 = pd.DataFrame({feature: temp.index, 'Number of contracts': temp.values})
cat_perc = application_train[[feature, 'TARGET']].groupby([feature], as_index=False).mean()
cat_perc.sort_values(by='TARGET', ascending=False, inplace=True)
if (horizontal_layout):
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12, 6))
else:
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12, 14))
sns.set_color_codes("pastel")
s = sns.barplot(ax=ax1, x=feature, y="Number of contracts", data=df1)
if (label_rotation):
s.set_xticklabels(s.get_xticklabels(), rotation=90)
s = sns.barplot(ax=ax2, x=feature, y='TARGET', order=cat_perc[feature], data=cat_perc)
if (label_rotation):
s.set_xticklabels(s.get_xticklabels(), rotation=90)
plt.ylabel('Percent of target with value 1 [%]', fontsize=10)
plt.tick_params(axis='both', which='major', labelsize=10)
plt.show()
plot_stats('NAME_CONTRACT_TYPE')
循環(huán)貸款只是貸款合同的小部分(10%左右)。與此同時撒桨,與循環(huán)貸款相比,現(xiàn)金貸款會有更大的幾率未償還孽椰。
客戶的性別
讓我們看看客戶的性別鹃愤,另外,在另一個圖上如绸,TARGET目標(biāo)值為1(貸款未按時償還)的貸款的百分比(按客戶性別劃分)
plot_stats('CODE_GENDER')
女性客戶的數(shù)量幾乎是男性客戶數(shù)量的兩倍嘱朽。從違約信貸的比例來看,男性不償還貸款的幾率(約10%)高于女性(約7%)怔接。
客戶有沒有車
讓我們看看客戶有沒有自己的車搪泳,另外,在另一個圖上扼脐,TARGET目標(biāo)值為1(貸款未按時償還)的貸款的百分比岸军。
plot_stats('FLAG_OWN_CAR')
擁有汽車的客戶幾乎是沒有汽車的客戶的一半。擁有汽車的客戶不太可能不償還擁有汽車的客戶的汽車瓦侮。沒有汽車的客戶違約率稍微高點(8%左右)
客戶有沒有房
讓我們看看客戶有沒有自己的房子艰赞,另外,在另一個圖上肚吏,TARGET目標(biāo)值為1(貸款未按時償還)的貸款的百分比方妖。
plot_stats('FLAG_OWN_REALTY')
擁有房產(chǎn)的客戶是不擁有房產(chǎn)的兩倍多。這兩類人(擁有房產(chǎn)或不擁有房產(chǎn))的違約率都在8%左右罚攀。
客戶家庭狀況
plot_stats('NAME_FAMILY_STATUS', True, True)
大多數(shù)客戶已婚党觅,其次是單身/未婚。
在不償還貸款比例方面斋泄,民事婚姻不償還比例最高(10%)杯瞻,寡婦最低。
兒童的數(shù)量
plot_stats('CNT_CHILDREN')
大多數(shù)貸款的客戶都沒有孩子炫掐。從圖中我們可以看到孩子越少的客戶越會去貸款又兵。
在還款方面,無子女、1沛厨、2宙地、3、5子女的客戶平均有10%左右沒有還款逆皮。對于有9宅粥、11個孩子的客戶,未償還貸款的比例為100%电谣。
客戶家庭人數(shù)
plot_stats('CNT_FAM_MEMBERS',True)
家庭成員為2人的客戶最多秽梅,其次為1人(單身人士)、3人(獨生子女家庭)和4人剿牺。
家庭成員分別為11人和13人的客戶有100%的違約率企垦。有10或8個成員的家庭有30%左右的違約率。擁有6名或6名以下家庭成員的違約率為10%的左右晒来。
客戶收入類型
plot_stats('NAME_INCOME_TYPE',False,False)
申請貸款的人大多是工作收入钞诡,其次是商業(yè)伙伴、養(yǎng)老金領(lǐng)取者和國家公務(wù)員湃崩。
產(chǎn)假的有近40%的違約率荧降,其次是失業(yè)(約37%)。其他類型的違約率均低于10%攒读。
客戶的職業(yè)
plot_stats('OCCUPATION_TYPE',True, False)
大部分貸款由勞動者承擔(dān)朵诫,其次是銷售人員。IT人員的最低薄扁。前幾天看了一篇推文發(fā)現(xiàn)學(xué)了IT的罪犯剪返,再犯率為0%。
違約率最高的是低技能勞動者(17%以上)邓梅,其次是司機随夸、服務(wù)員/酒吧服務(wù)員、保安震放、勞動者和廚師。
行業(yè)類型
plot_stats('ORGANIZATION_TYPE',True, False)
違約率最高的行業(yè)是運輸業(yè):第3類(16%)驼修、工業(yè):第13類(13.5%)殿遂、工業(yè):第8類(12.5%)和餐飲業(yè)(不到12%)。
客戶的教育類型
plot_stats('NAME_EDUCATION_TYPE',True)
大部分客戶接受中等/中等特殊教育乙各,其次是接受高等教育的客戶墨礁。只有極少數(shù)人擁有學(xué)位。
初中畢業(yè)的貸款雖然很少見耳峦,但不還貸率最高(11%)恩静。擁有學(xué)位的人的不償還率低于2%。
客戶房屋類型
plot_stats('NAME_HOUSING_TYPE',True)
25萬多名申請貸款的人將他們的住房登記為住房/公寓。
從這些類別來看驶乾,租來的公寓和跟父母一起住的高于10%的違約率邑飒。
Bureau數(shù)據(jù)集
讓我們將application_train與bureau合并。
application_bureau_train = application_train.merge(bureau, left_on='SK_ID_CURR', right_on='SK_ID_CURR', how='inner')
print("The resulting dataframe `application_bureau_train` has ",application_bureau_train.shape[0]," rows and ",
application_bureau_train.shape[1]," columns.")
The resulting dataframe `application_bureau_train` has 1465325 rows and 138 columns.
現(xiàn)在讓我們分析application_bureau_train數(shù)據(jù)级乐。
def plot_b_stats(feature,label_rotation=False,horizontal_layout=True):
temp = application_bureau_train[feature].value_counts()
df1 = pd.DataFrame({feature: temp.index,'Number of contracts': temp.values})
# Calculate the percentage of target=1 per category value
cat_perc = application_bureau_train[[feature, 'TARGET']].groupby([feature],as_index=False).mean()
cat_perc.sort_values(by='TARGET', ascending=False, inplace=True)
if(horizontal_layout):
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,6))
else:
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12,14))
sns.set_color_codes("pastel")
s = sns.barplot(ax=ax1, x = feature, y="Number of contracts",data=df1)
if(label_rotation):
s.set_xticklabels(s.get_xticklabels(),rotation=90)
s = sns.barplot(ax=ax2, x = feature, y='TARGET', order=cat_perc[feature], data=cat_perc)
if(label_rotation):
s.set_xticklabels(s.get_xticklabels(),rotation=90)
plt.ylabel('Percent of target with value 1 [%]', fontsize=10)
plt.tick_params(axis='both', which='major', labelsize=10)
plt.show()
信用狀態(tài)
讓我們看看信用狀況分布疙咸。我們首先顯示每個類別的信貸數(shù)量(可以是關(guān)閉的、活躍的风科、出售的和壞賬)撒轮。
plot_b_stats('CREDIT_ACTIVE')
我們可以看出大約有900000人的狀態(tài)是closed,Bad debt的狀態(tài)是最少的贼穆。
但我們可以看到Bad debt的違約率是最高的题山,是其他狀態(tài)的兩倍多。
信用貨幣
plot_b_stats('CREDIT_CURRENCY')
從圖上我們可以看出故痊,幾乎全都是currency_1貸款顶瞳。
根據(jù)貨幣的不同,客戶違約的比例是不同的崖蜜。從currency_3開始浊仆,然后是currency_1和currency_2,違約的百分比分別是11%豫领、8%和5%抡柿。currency_4的違約率約為0%。
信用類型
plot_b_stats('CREDIT_TYPE', True, True)
在 Credit Bureau登記的歷史信用主要是消費信貸和信用卡等恐。
購買設(shè)備的貸款——違約率超過20%;
小額貸款——違約率超過20%;
流動資金補充貸款——違約率超過12%洲劣。
Previous application數(shù)據(jù)集
讓我們將application_train與previous_application合并。
application_prev_train = application_train.merge(previous_application, left_on='SK_ID_CURR', right_on='SK_ID_CURR', how='inner')
print("The resulting dataframe `application_prev_train` has ",application_prev_train.shape[0]," rows and ",
application_prev_train.shape[1]," columns.")
The resulting dataframe `application_prev_train` has 1413701 rows and 158 columns.
def plot_p_stats(feature,label_rotation=False,horizontal_layout=True):
temp = application_prev_train[feature].value_counts()
df1 = pd.DataFrame({feature: temp.index,'Number of contracts': temp.values})
# Calculate the percentage of target=1 per category value
cat_perc = application_prev_train[[feature, 'TARGET']].groupby([feature],as_index=False).mean()
cat_perc.sort_values(by='TARGET', ascending=False, inplace=True)
if(horizontal_layout):
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12,6))
else:
fig, (ax1, ax2) = plt.subplots(nrows=2, figsize=(12,14))
sns.set_color_codes("pastel")
s = sns.barplot(ax=ax1, x = feature, y="Number of contracts",data=df1)
if(label_rotation):
s.set_xticklabels(s.get_xticklabels(),rotation=90)
s = sns.barplot(ax=ax2, x = feature, y='TARGET', order=cat_perc[feature], data=cat_perc)
if(label_rotation):
s.set_xticklabels(s.get_xticklabels(),rotation=90)
plt.ylabel('Percent of target with value 1 [%]', fontsize=10)
plt.tick_params(axis='both', which='major', labelsize=10)
plt.show()
合同類型
plot_p_stats('NAME_CONTRACT_TYPE_y')
在之前的申請數(shù)據(jù)中有三種類型的合同:現(xiàn)金貸款课蔬、消費貸款囱稽、循環(huán)貸款。現(xiàn)金貸款和消費貸款幾乎相同(約60萬)二跋,而循環(huán)貸款約15萬战惊。
之前申請過的客戶違約率因之前申請合同的類型而異,循環(huán)貸款的違約率為10%扎即,現(xiàn)金貸款的違約率為9.5%吞获,消費貸款的違約率為8%。
現(xiàn)金貸款的目的
plot_p_stats('NAME_CASH_LOAN_PURPOSE', True, True)
除XAP谚鄙、XNA各拷、修理、其他以外闷营,購買二手車烤黍、建造房屋占合同數(shù)量最多。
合同狀態(tài)
plot_p_stats('NAME_CONTRACT_STATUS', True, True)
大部分的合同狀態(tài)是批準(zhǔn)的,其次是取消和拒絕的速蕊。
合同狀態(tài)為拒絕的違約率最高(約12%)嫂丙,其次是取消的(約9%),違約率最低的是批準(zhǔn)的(不到8%)互例。
付款類型
plot_p_stats('NAME_PAYMENT_TYPE', True, True)
大部分的付款類型是通過銀行的奢入,其次是XNA。
除了XNA(違約率最高)媳叨,其他的違約率約為8%腥光。
結(jié)論
EDA到此為止,我們可以根據(jù)EDA創(chuàng)建一些新的特征糊秆、清洗數(shù)據(jù)等等武福。