上一篇網貸平臺Prosper2005~2014貸款數據分析(一)中,主要重要變量的介紹、幾個重要變量的轉換、數據的探索性分析。接下來,主要介紹數據缺失處理、模型分析和預測。
六、缺失值處理
主要變量的缺失值,只顯示存在缺失的變量,獲取其缺失數量,以及缺失率,代碼實現如下:
missing=pd.concat([loanData.isnull().any(),loanData.count()],axis=1)
column=['是否缺失','數量']
missing=pd.DataFrame(list(missing.values),index=list(missing.index),columns=column)
max=missing['數量'].max()
missing['缺失數量']=max-missing['數量']
missing['缺失率']=missing['缺失數量']/max
miss=missing[missing['數量']<max]
其缺失情況如圖6-1所示。從上表中,可知代表信用等級的CreditGrade和ProsperRating (Alpha)變量缺失值較多,是因為平臺是以2009年7月為分界點,使用不一樣的評級方法而產生。
6.1 CreditScore缺失值處理
CreditScore缺失了590條,所占比例約為0.5%左右,所占比例不大,考慮模型的精確性,建議暫時用中位數進行替換。
#用中位數替換CreditScore的缺失值
loanData['CreditScore']=loanData['CreditScore'].fillna(loanData['CreditScore'].median())
6.2 BorrowerState缺失值處理
BorrowerState缺失值5512條,所占比例約5%,缺失比例較大,所以可以考慮將缺失值單獨作為一項因子,暫時設置為“NOTA”。
#將缺失值單獨作為一項因子,設置為“NOTA”
loanData['BorrowerState']=loanData['BorrowerState'].fillna('NOTA')
6.3 DebtToIncomeRatio缺失值處理
DebtToIncomeRatio缺失值為8554條,所占比例很大,且違約比例較大,依據常識債務比例數值越大違約的概率越大,所以根據數據集中債務比例分布情況將0.10~0.50隨機賦值給缺失的DebtToIncomeRatio。設置隨機賦值的定義函數:
#DebtToIncomeRatio缺失值添加隨機數
def rand_missing(s):
if s>=0:
a=s
else:
a=random.uniform(0.1,0.5)
return a
對缺失值進行賦值:
#DebtToIncomeRatio的缺失值添加0.1~0.5的隨機變量
loanData['DebtToIncomeRatio']=loanData['DebtToIncomeRatio'].apply(rand_missing)
6.3 DelinquenciesLast7Years缺失值處理
DelinquenciesLast7Years缺失值為987條,在平臺借款違約比例較大,所以將DelinquenciesLast7Years缺失值全部置為1。
#將DelinquenciesLast7Years的缺失值賦值為1
loanData['DelinquenciesLast7Years'] = loanData['DelinquenciesLast7Years'].fillna(1)
6.4 EmploymentStatusDuration缺失值處理
EmploymentStatusDuration缺失值為7621條,所占比例很大,且違約比例很大。猜想,工作越穩定還款能力越強,故將EmploymentStatusDuration的缺失值置為48。
#EmploymentStatusDuration缺失值處理,設置為48
loanData['EmploymentStatusDuration'] = loanData['EmploymentStatusDuration'].fillna(48)
6.5 InquiriesLast6Months缺失值處理
InquiriesLast6Months缺失值為696條,所占比例不大,違約比例跟整體數據相近,故將InquiriesLast6Months的缺失值置為2。
#將InquiriesLast6Months的缺失值置為2
loanData['InquiriesLast6Months'] = loanData['InquiriesLast6Months'].fillna(2)
6.6 ProsperRating (Alpha)缺失處理
在2009年之后,大約有3萬條,篩選出ProsperRating (Alpha)變量的缺失值,大約有144條,所占比例較小,所以采用直接刪除的方式進行處理。
#2009之后,選出ProsperRating (Alpha)為空的行,然后對行進行刪除
missIndex=loanData[(loanData['ProsperRating (Alpha)'].isnull()) & (loanData['DatePhase']=='After Jul.2009')]
loanData=loanData.drop(missIndex.index,axis=0)
七、建模分析
7.1 字符串變量轉換成數字變量
數據中存在字符串變量,將其用數字變量進行替換。實現的函數如下:
#定性變量的賦值
def harmonize_data(df):
# 填充空數據 和 把string數據轉成integer表示
#Status
df.loc[df['Status']=='Completed','Status']=1
df.loc[df['Status'] == 'Defaulted', 'Status'] = 0
df.loc[df['Status'] == 'Current', 'Status'] = 2
#IsBorrowerHomeowner
df.loc[df['IsBorrowerHomeowner'] == False, 'IsBorrowerHomeowner'] = 0
df.loc[df['IsBorrowerHomeowner'] == True, 'IsBorrowerHomeowner'] = 1
#CreditGrade
df.loc[df['CreditGrade'] == 'NC', 'CreditGrade'] = 0
df.loc[df['CreditGrade'] == 'HR', 'CreditGrade'] = 1
df.loc[df['CreditGrade'] == 'E', 'CreditGrade'] = 2
df.loc[df['CreditGrade'] == 'D', 'CreditGrade'] = 3
df.loc[df['CreditGrade'] == 'C', 'CreditGrade'] = 4
df.loc[df['CreditGrade'] == 'B', 'CreditGrade'] = 5
df.loc[df['CreditGrade'] == 'A', 'CreditGrade'] = 6
df.loc[df['CreditGrade'] == 'AA', 'CreditGrade'] = 7
#ProsperRating (Alpha)
df.loc[df['ProsperRating (Alpha)'] == 'HR', 'ProsperRating (Alpha)'] = 1
df.loc[df['ProsperRating (Alpha)'] == 'E', 'ProsperRating (Alpha)'] = 2
df.loc[df['ProsperRating (Alpha)'] == 'D', 'ProsperRating (Alpha)'] = 3
df.loc[df['ProsperRating (Alpha)'] == 'C', 'ProsperRating (Alpha)'] = 4
df.loc[df['ProsperRating (Alpha)'] == 'B', 'ProsperRating (Alpha)'] = 5
df.loc[df['ProsperRating (Alpha)'] == 'A', 'ProsperRating (Alpha)'] = 6
df.loc[df['ProsperRating (Alpha)'] == 'AA', 'ProsperRating (Alpha)'] = 7
#IncomeRange
df.loc[df['IncomeRange'] == 'Not displayed', 'IncomeRange'] = 0
df.loc[df['IncomeRange'] == 'Not employed', 'IncomeRange'] = 1
df.loc[df['IncomeRange'] == '$0', 'IncomeRange'] = 2
df.loc[df['IncomeRange'] == '$1-24,999', 'IncomeRange'] = 3
df.loc[df['IncomeRange'] == '$25,000-49,999', 'IncomeRange'] = 4
df.loc[df['IncomeRange'] == '$50,000-74,999', 'IncomeRange'] = 5
df.loc[df['IncomeRange'] == '$75,000-99,999', 'IncomeRange'] = 6
df.loc[df['IncomeRange'] == '$100,000+', 'IncomeRange'] = 7
#BankCardUse
df.loc[df['BankCardUse'] == 'No Use', 'BankCardUse'] = 0
df.loc[df['BankCardUse'] == 'Mild Use', 'BankCardUse'] = 1
df.loc[df['BankCardUse'] == 'Medium Use', 'BankCardUse'] = 2
df.loc[df['BankCardUse'] == 'Heavy Use', 'BankCardUse'] = 3
df.loc[df['BankCardUse'] == 'Super Use', 'BankCardUse'] = 4
#CustomerClarify
df.loc[df['CustomerClarify'] == 'New Borrower', 'CustomerClarify'] = 0
df.loc[df['CustomerClarify'] == 'Previous Borrower', 'CustomerClarify'] = 1
return df
#字符串替換成整數
loanData=harmonize_data(loanData)
7.2 建模分析(2009.07.01之前)
7.2.1 數據建模
為了評估分類器的性能,將數據集分成訓練集和測試集,為了獲取各變量對違約情況的影響的重要程度,可以考慮用隨機森林算法。
loanData = loanData[loanData['Status'] != 2]
before2009=loanData[loanData['DatePhase']=='Before Jul.2009']
Y=before2009['Status']
X=before2009[['CreditGrade','CustomerClarify','IncomeRange','DebtToIncomeRatio','DelinquenciesLast7Years','BorrowerRate','IsBorrowerHomeowner','ListingCategory (numeric)','EmploymentStatusDuration','InquiriesLast6Months','CreditScore','BankCardUse']]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)
rfr=RandomForestClassifier()
rfr.fit(X_train,Y_train)
7.2.2 模型評估
將分配的30%的測試集,對訓練出的模型進行評估。
#測試集進行預測
result=rfr.predict(X_test)
對預測的準確率進行計算:
def accuracy_statistics(rd,prd):
count=len(prd)
sum=0
for i in range(1,count):
if rd[i]==prd[i]:
sum += 1
pecent=round(sum/count,4)
return pecent
pecent=accuracy_statistics(list(Y_test.values),list(result))
該模型預測結果的準確率為(1498+4520)/8385=71.77%。
7.2.3 變量的重要性
對于一個決策樹森林來說,可以算出每個特征平均減少了多少不純度,并把它平均減少的不純度作為特征選擇的值,可以獲取變量的重要程度。
featureImp=pd.Series(rfr.feature_importances_,index=list(X_train.columns)).sort_values(ascending=False)
fig2 = plt.figure(2)
ax2 = fig2.add_subplot(1, 1, 1)
featureImp.plot(kind='barh',ax=ax2)
ax2.set_xlabel('重要程度',fontsize=14)
plt.show()
如圖7-1所示,對模型預測結果的準確率影響最大的前三個變量為BorrowerRate,DebtToIncomeRatio,EmploymentStatusDuration。7.3 建模分析(2009.07.01之后)
7.3.1 數據建模
2009年7月后數據集的分配,代碼實現如下:
afterData = loanData[loanData['Status'] != 2]
after2009=afterData[afterData['DatePhase']=='After Jul.2009']
Y=after2009['Status']
X=after2009[['ProsperRating (Alpha)','CustomerClarify','IncomeRange','DebtToIncomeRatio','DelinquenciesLast7Years','BorrowerRate','IsBorrowerHomeowner','ListingCategory (numeric)','EmploymentStatusDuration','InquiriesLast6Months','CreditScore','BankCardUse']]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0)
rfr=RandomForestClassifier()
rfr.fit(X_train,Y_train)
7.3.2 模型評估
將分配的30%的測試集,對訓練出的模型進行評估。
#測試集進行預測
result=rfr.predict(X_test)
對預測的準確率進行計算:
def accuracy_statistics(rd,prd):
count=len(prd)
sum=0
for i in range(1,count):
if rd[i]==prd[i]:
sum += 1
pecent=round(sum/count,4)
return pecent
pecent=accuracy_statistics(list(Y_test.values),list(result))
該模型預測結果的準確率為(161+6382)/8484=77.12%。
7.3.3 變量的重要性
如圖7-2所示,對模型預測結果的準確率影響最大的前三個變量為EmploymentStatusDuration,BorrowerRate,DebtToIncomeRatio。7.4 小結
2009.07.01前后的模型變量重要性相比,EmploymentStatusDuration由第三位變為第一位,說明在2009.07.01之后的模型更加強調雇傭狀態持續時間的重要性,從模型預測的準確率來看,這種模型的調整是有效的,使得準確率由71.77%增加到77.12%。
八、數據預判
根據2009年后的模型,對正在貸款狀態的客戶可能違約情況進行預測。
#正在貸款的人還款預測
currentData=loanData[loanData['Status']==2]
current=currentData[['ProsperRating (Alpha)','CustomerClarify','IncomeRange','DebtToIncomeRatio','DelinquenciesLast7Years','BorrowerRate','IsBorrowerHomeowner','ListingCategory (numeric)','EmploymentStatusDuration','InquiriesLast6Months','CreditScore','BankCardUse']]
currentPredict=rfr.predict(current)
currentData.loc[(currentData.Status.notnull()),'Status'] = currentPredict
currentData.to_csv('PredictData.csv',index=False)
將數據的結果保存到csv文件中,如圖7-3所示,Status變量中,1代表將會還款,0代表可能違約。可以計算56576條正在貸款的客戶,整體的違約率,實現代碼如下:
defaultedRate=1-(currentPredict.sum()/len(currentPredict))
正在貸款的客戶整體的違約率1-(53037/56576)=6.3%。
九、總結
本文詳述了如何通過數據預覽,基本數據分析、探索式數據分析,缺失數據填補等方法,實現對kaggle上Prosper借貸平臺貸款者還款與否這一分類問題如何進行數據分析的具體探索式實踐。分別對2009.07.01前后的模型進行建模分析對比,得出兩個模型的預測準確率和變量對模型的重要性對比分析,明確看出2009.07.01前后平臺的模型明顯有很大的不同。在基于2009年后模型,對正在貸款狀態的客戶的違約可能性進行預測。