1.摘要
本文主要描述了如何用Python對(duì)數(shù)據(jù)集進(jìn)行評(píng)估捂敌,整理轰胁,清洗惩坑。
完成這一過(guò)程后掉盅,再通過(guò)Tableau對(duì)問(wèn)題“Prosper違約客戶具有哪些特點(diǎn)”進(jìn)行探索,分析和可視化旭贬。
最后怔接,用隨機(jī)森林算法對(duì)2009年7月后數(shù)據(jù)進(jìn)行建模分析,并對(duì)仍在進(jìn)行中的貸款進(jìn)行違約與否的預(yù)測(cè)稀轨。
2.項(xiàng)目背景介紹
Prosper是美國(guó)第一家P2P借貸平臺(tái)扼脐。此數(shù)據(jù)集來(lái)源于Udacity上的Prosper 2005~2014年的貸款數(shù)據(jù)。本文希望能通過(guò)對(duì)已完成貸款的分析奋刽,判斷出什么類型的客戶更容易違約瓦侮,并預(yù)測(cè)還未完成的貸款是否會(huì)違約。
3.數(shù)據(jù)變量
原始數(shù)據(jù)集共包含81個(gè)變量佣谐,113937條數(shù)據(jù)肚吏,下面對(duì)部分重要變量進(jìn)行說(shuō)明,其他變量含義可參考變量詞典狭魂。
4.數(shù)據(jù)處理
首先加載庫(kù)和數(shù)據(jù)罚攀。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
#導(dǎo)入數(shù)據(jù)
df = pd.read_csv('prosperLoanData.csv')
df.head()
然后用df.describe(),df.info()觀察數(shù)據(jù)雌澄。
4.1 刪除無(wú)關(guān)變量
此次主要分析1.什么類型的借款人更容易違約斋泄。 2.預(yù)測(cè)未完成的貸款是否會(huì)發(fā)生違約。所以去掉無(wú)關(guān)列镐牺。
- 冗余的編號(hào)列:ListingKey, ListingNumber炫掐,LoanNumber等。
- 僅與投資人相關(guān)列:LP_CustomerPayments,LP_ServiceFees等睬涧。
#刪除無(wú)關(guān)列
df = df.drop(['ListingKey', 'ListingNumber','LenderYield', 'EstimatedEffectiveYield', 'EstimatedLoss',
'EstimatedReturn','LoanKey', 'LoanNumber', 'MemberKey','LP_CustomerPayments',
'LP_CustomerPrincipalPayments', 'LP_InterestandFees', 'LP_ServiceFees',
'LP_CollectionFees', 'LP_GrossPrincipalLoss', 'LP_NetPrincipalLoss',
'LP_NonPrincipalRecoverypayments', 'PercentFunded', 'Recommendations',
'InvestmentFromFriendsCount', 'InvestmentFromFriendsAmount',
'Investors'],axis=1)
從2009年7月開始募胃,Prosper調(diào)整了對(duì)客戶的評(píng)估方式旗唁,此次我們只對(duì)2009-07-01后的貸款進(jìn)行分析。
#篩選2009-07-01后的數(shù)據(jù)
df = df[df['ListingCreationDate']>'2009-7-1']
去掉意義重復(fù)列:
- BorrowerAPR,BorrowerRate直接相關(guān)痹束,只對(duì)BorrowerAPR進(jìn)行分析检疫;
- ProsperRating (numeric),ProsperRating (Alpha)只是不同表達(dá)形式,只使用ProsperRating (Alpha)参袱;
- CreditScoreRangeUpper电谣,CreditScoreRangeLower直接相關(guān)秽梅,只用CreditScoreRangeLower抹蚀。
#去掉意義重復(fù)列
df = df.drop(['BorrowerRate','ProsperRating (numeric)',
'CreditScoreRangeUpper'],axis=1)
Prosper對(duì)于新客戶的評(píng)分和老客戶有所區(qū)別,此次僅針對(duì)新客戶數(shù)據(jù)進(jìn)行分析企垦。
#篩選出新客戶
df = df[df['TotalProsperLoans'].isnull()]
#去掉與新客戶無(wú)關(guān)列
df = df.drop(['CreditGrade', 'TotalProsperLoans','TotalProsperPaymentsBilled',
'OnTimeProsperPayments', 'ProsperPaymentsLessThanOneMonthLate',
'ProsperPaymentsOneMonthPlusLate', 'ProsperPrincipalBorrowed',
'ProsperPrincipalOutstanding','ScorexChangeAtTimeOfListing'],axis=1)
4.2 缺失值處理
首先查看下环壤,各變量數(shù)據(jù)缺失情況。
missing = pd.concat([df.isnull().any(),df.count()], axis =1)
column = ['是否缺失','數(shù)量']
missing = pd.DataFrame(list(missing.values),index = list(missing.index),columns = column)
total = missing['數(shù)量'].max()
missing['缺失數(shù)量'] = total - missing['數(shù)量']
missing['缺失率'] = missing['缺失數(shù)量']/total
miss = missing[missing['是否缺失'] == True]
miss
- 刪除缺失率過(guò)大的變量:ClosedDate钞诡,GroupKey郑现, LoanFirstDefaultedCycleNumber
- Occupation列:缺失1307條荧降,用‘Other’替換 NaN朵诫。
- EmploymentStatusDuration列:僅缺少15條剪返,直接刪除缺失的數(shù)據(jù)邑滨。
- DebtToIncomeRatio列:缺失5124條掖看,缺失率較高。因?yàn)榻^大部分?jǐn)?shù)值在0.5以下耳峦,所以在0-0.5之間隨機(jī)賦值蹲坷。
#處理空值
df = df.drop(['ClosedDate','GroupKey',
'LoanFirstDefaultedCycleNumber'],axis = 1)
df.Occupation = df.Occupation.fillna('Other')
df.dropna(subset = ['EmploymentStatusDuration'],inplace = True)
#為DebtToIncomeRatio列空值賦值
def ratio(s):
if s>= 0:
a=s
else:
a=np.random.uniform(0,0.5)
return a
df.DebtToIncomeRatio = df.DebtToIncomeRatio.apply(ratio)
4.3 數(shù)據(jù)轉(zhuǎn)換
- 為了便于處理级乐,將ProsperScore,CreditScoreRangeLower,
EmploymentStatusDuration格式轉(zhuǎn)為int。
#格式轉(zhuǎn)換
df['ProsperScore'] = df.ProsperScore.astype(int)
df['CreditScoreRangeLower'] = df.CreditScoreRangeLower.astype(int)
df['EmploymentStatusDuration'] = df.EmploymentStatusDuration.astype(int)
- LoanStatus數(shù)據(jù)變換
平臺(tái)把借款狀態(tài)分為12種:Cancelled(取消)、Chargedoff(沖銷故痊,投資人有損失)、Completed(正常完成戴甩,投資人無(wú)損失)、Current(貸款還款中)课蔬、Defaulted(壞賬,投資人有損失)、FinalPaymentInProgress(最后還款中谚鄙,投資人無(wú)損失)闷营、Past Due(逾期還款速蕊,投資人無(wú)損失)。
本文依據(jù)交易是仍在進(jìn)行中還是已關(guān)閉,以及已關(guān)閉交易中投資人有無(wú)損失將所有數(shù)據(jù)分成以下三組:
Current(包含Current,Past Due)、
Defaulted(包含Defaulted,Chargedoff)袄简、
Completed(包含Completed,FinalPaymentInProgress)。
為了便于后續(xù)分析計(jì)算,再將“Completed”改為1宗雇,“Defaulted”改為0赔蒲。
# LoanStatus變換
def loan_status(s):
if s=='Defaulted':
a = 0
elif s=='Chargedoff':
a = 0
elif s=='Completed':
a = 1
elif s == 'FinalPaymentInProgress':
a = 1
else:
a='Current'
return a
# 新建一個(gè)Status變量
df['Status'] = df['LoanStatus'].apply(loan_status)
#將數(shù)據(jù)集分成已完成(Loandata_finished)和未完成(Loandata_unfinished)兩個(gè)文件
df_finished = df[df['Status']!='Current']
df_unfinished = df[df['Status']=='Current']
#保存數(shù)據(jù)
df.to_csv('LoanData_clean.csv')
df_finished.to_csv('LoanData_finished.csv')
df_unfinished.to_csv('LoanData_unfinished.csv')
#計(jì)算違約率
defaulted_ratio_finished = 1-df_finished.Status.mean()
defaulted_ratio_finished
已完成的貸款的違約率為defaulted_ratio_finished =26.07%
5.使用Tableau進(jìn)行數(shù)據(jù)探索
5.1 信用情況與壞賬率
此數(shù)據(jù)集有多個(gè)特征體現(xiàn)了貸款用戶的信用情況母市。其中椅寺,信用等級(jí)(ProsperRating)是Prosper根據(jù)自身模型建立,是用于確定貸款利率的主要依據(jù),而信用評(píng)分(CreditScore)則是由官方信用評(píng)級(jí)機(jī)構(gòu)提供邑闲。
由圖5-1可以看到苫耸,隨著信用等級(jí)(ProsperRating)的不斷升高,違約率呈現(xiàn)明顯的下降趨勢(shì)。
而在信用評(píng)分(CreditScore)中笼痛,低分段(640-700)进宝,違約率處于比較高的位置谭胚,且沒(méi)有太大變化。大于720的部分旁趟,隨著信用評(píng)分的升高敛劝,違約率明顯下降蛾方。
說(shuō)明整體而言,借款人的信用水平越高,違約可能性越低。
5.2 收入與違約率
在不同年收入(IncomeRange)中,Not employed的借款人,違約率最高,隨著收入增加,違約率不斷降低人柿。
在不同貸款狀態(tài)下(Status)哥放,違約用戶的整體月收入(MonthlyIncome)明顯低于未違約用戶。
5.3 負(fù)債收入比與違約率
根據(jù)圖5-4的左圖,違約用戶與未違約用戶的整體負(fù)債收入比差異不大。
再根據(jù)負(fù)債收入比(DebtToIncome)的四分位點(diǎn)省撑,將所有數(shù)據(jù)分成數(shù)據(jù)量接近的四組。從圖5-4的右圖可以看到低比例(負(fù)債收入比0-0.12)與中等比例(0.12-0.19)的違約率都較低。較高比例(0.19-0.29)的違約率略高于前面二者。但高比例(大于0.29)的用戶違約率顯著升高佛舱。
5.4 銀行卡額度透支率與違約率
根據(jù)銀行卡額度透支率(BankcardUtilization)的四分位點(diǎn)刷晋,將數(shù)據(jù)分成 '未使用'捏悬,'較低透支(0,0.3]'抒和,'中等透支(0.3,0.7]'镊辕, '較高透支(0.7,1]'石咬,'嚴(yán)重透支(1,5]'五組。
可以看到卖哎,嚴(yán)重透支的借款人鬼悠,違約率最高。
其次是未使用的用戶亏娜,這也是為什么金融機(jī)構(gòu)對(duì)于“白戶”會(huì)格外關(guān)注的原因焕窝。
5.5 征信查詢次數(shù)與違約率
近半年征信查詢次數(shù)(InquiriesLast6Months)可以反應(yīng)出借款人近期向金融機(jī)構(gòu)申請(qǐng)借款的頻繁程度,間接體現(xiàn)了借款人近期的資金狀況维贺。
圖5-6中它掂,綠線表示不同查詢次數(shù)下的借款筆數(shù)∷萜可以看到虐秋,絕大部分在7次以下。
而在查詢次數(shù)0-7區(qū)間內(nèi)垃沦,違約率隨著查詢次數(shù)的增加而升高熟妓。
5.6 當(dāng)前逾期與違約率
當(dāng)前逾期(CurrentDelinquencies)可以很好的反應(yīng)出借款人的信用情況。
由圖5-7栏尚,可以看到大部分借款人的當(dāng)前逾期在2次以內(nèi)。而在0-6的區(qū)間內(nèi)只恨,違約率隨當(dāng)前逾期數(shù)的增加而升高译仗。
5.7 申請(qǐng)信息與違約率
5.7.1 申請(qǐng)理由(ListingCategory)
為了避免某些數(shù)量極少的分類對(duì)違約率排序的影響,首先篩選出借款筆數(shù)在30以上的分類官觅。
由圖5-8可以看到纵菌,數(shù)量最多的是1- Debt Consolidation(債務(wù)整合)。
而違約率最高的依次是15- Medical/Dental(醫(yī)療),13-Household Expenses(家庭開支),3-Business(商業(yè))休涤,均高于30%咱圆。
5.7.2 貸款金額(LoanAmount)
根據(jù)貸款金額(LoanAmount)的四分位點(diǎn)笛辟,將數(shù)據(jù)分為數(shù)量接近的四組。比較有意思的是序苏,中等借款(3100,4750)的違約率最高手幢,而高額借款(大于8500)的違約率反而最低。
這很可能是因?yàn)槟苌暾?qǐng)到高額借款的用戶忱详,各方面條件都不錯(cuò)围来,從而降低了違約率。
5.8 受雇傭狀態(tài)持續(xù)時(shí)間與違約率
由圖5-11可以看到匈睁,在0-30區(qū)間內(nèi)监透,隨著持續(xù)時(shí)間的增長(zhǎng),違約率逐漸降低航唆,而這一區(qū)間也包含了一半左右的數(shù)據(jù)胀蛮。
當(dāng)持續(xù)時(shí)間繼續(xù)增長(zhǎng),違約率看不出有明顯變化規(guī)律糯钙。
5.9 地區(qū)與違約率
在不同地區(qū)之間粪狼,違約率也存在比較明顯的差異。LA,SD等城市超营,違約率較高鸳玩。UT,CO等城市,違約率較低演闭。
5.10 是否擁有房產(chǎn)與違約率
整體而言不跟,有房產(chǎn)的借款人,違約率要明顯低于無(wú)房產(chǎn)的借款人米碰。
6.建模分析
導(dǎo)入相關(guān)庫(kù)窝革。
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import LabelEncoder
6.1 數(shù)據(jù)轉(zhuǎn)換
將數(shù)據(jù)中的字符串變量,均轉(zhuǎn)換為數(shù)字吕座。
#將字符串變量用相應(yīng)的數(shù)字變量替換
def harmonize_data(df):
#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
#IsBorrowerHomeowner
df.loc[df['IsBorrowerHomeowner'] == True, 'IsBorrowerHomeowner'] =1
df.loc[df['IsBorrowerHomeowner'] == False, 'IsBorrowerHomeowner'] =0
#BorrowerState
le = LabelEncoder().fit(df['BorrowerState'])
df.loc[:,'BorrowerState'] = le.transform(df['BorrowerState'])
#IncomeRange
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
return df
df_finished = harmonize_data(df_finished)
#格式轉(zhuǎn)換
df_finished['Status'] = df_finished.Status.astype(int)
6.2 建立模型
按照測(cè)試集30%虐译,訓(xùn)練集70%的比例劃分?jǐn)?shù)據(jù)集,并使用隨機(jī)森林算法吴趴,建立模型漆诽。
Y = df_finished['Status']
X = df_finished[['ProsperRating (Alpha)','IncomeRange','DebtToIncomeRatio',
'BankcardUtilization','StatedMonthlyIncome',
'IsBorrowerHomeowner','ListingCategory (numeric)',
'EmploymentStatusDuration', 'InquiriesLast6Months',
'CreditScoreRangeLower','BorrowerState',
'CurrentDelinquencies', 'LoanOriginalAmount']]
#劃分?jǐn)?shù)據(jù)集
X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.3,random_state=42)
#建立模型
clf = RandomForestClassifier(random_state=42,n_estimators = 200)
clf.fit(X_train,Y_train)
6.3 模型評(píng)估
#對(duì)測(cè)試集進(jìn)行預(yù)測(cè)
result = clf.predict(X_test)
#計(jì)算準(zhǔn)確率
accuracy = clf.score(X_test,Y_test)
accuracy
該模型測(cè)試集預(yù)測(cè)準(zhǔn)確率為:accuracy=73.99%
6.4 特征重要性
對(duì)于隨機(jī)森林算法,可以查看在這個(gè)模型中锣枝,每個(gè)特征的重要程度厢拭。
#查看各特征的重要性
FeatureImp = pd.Series(clf.feature_importances_,index=list(X_train.columns)).sort_values(ascending=False)
FeatureImp
#特征重要性作圖
FeatureImp.sort_values().plot(kind='barh')
plt.xlabel('Feature Importance');
如圖6-2所示,StatedMonthlyIncome和EmploymentStatusDuration兩個(gè)特征最為重要撇叁。
6.5 數(shù)據(jù)預(yù)測(cè)
根據(jù)此模型供鸠,對(duì)目前仍在進(jìn)行中的貸款進(jìn)行違約與否的預(yù)測(cè)。
#數(shù)據(jù)預(yù)測(cè)
df_unfinished = harmonize_data(df_unfinished)
unfinished = df_unfinished[['ProsperRating (Alpha)','IncomeRange','BorrowerState',
'DebtToIncomeRatio', 'BankcardUtilization',
'StatedMonthlyIncome', 'IsBorrowerHomeowner',
'ListingCategory (numeric)','EmploymentStatusDuration',
'InquiriesLast6Months','CreditScoreRangeLower',
'CurrentDelinquencies','LoanOriginalAmount']]
unfinished_predict = clf.predict(unfinished)
#保存預(yù)測(cè)數(shù)據(jù)
df_unfinished.to_csv('LoanData_unfinished_predict.csv')
#計(jì)算違約率
defaulted_ratio_predict = 1-df_unfinished['StatusPredict'].mean()
defaulted_ratio_predict
仍在進(jìn)行中的貸款違約率為defaulted_ratio_predict =3.64%
7.總結(jié)
本文詳細(xì)描述了對(duì)于Prosper貸款數(shù)據(jù)陨闹,從數(shù)據(jù)探索到建立模型楞捂,并進(jìn)行預(yù)測(cè)的完整過(guò)程薄坏。
發(fā)現(xiàn)月收入(StatedMonthlyIncome)以及受雇傭狀態(tài)持續(xù)時(shí)間(EmploymentStatusDuration)對(duì)是否會(huì)違約的影響程度最大。主要是因?yàn)檫@二者是體現(xiàn)借款人穩(wěn)定性的重要因素寨闹。
而在模型建立方面胶坠,還可以調(diào)整此模型的參數(shù),來(lái)進(jìn)行改進(jìn)從而提高準(zhǔn)確率鼻忠,也可以嘗試使用其他算法涵但,如邏輯回歸等,建立新的模型進(jìn)行比較帖蔓。