赞
踩
使用R语言对银行的个人贷款是否违约进行预测,帮助业务部门及时发现问题,以避免损失。
本项目数据集来自《数据科学实战:Python篇》。数据集包含8个表:账户表accounts、信用卡表card、客户信息表clients、权限分配表disp、人口地区统计表district、贷款表loans、支付订单表order、交易表trans。
贷款表(Loans)是该项目问题的核心数据表,每个贷款帐户只有一条记录,故将所有维度的信息归结到贷款表(LOANS)上。首先提取的自变量是客户基本信息:性别、年龄等。客户的人口信息保存在客户信息表(ClIENTS)中,但是该表是以客户为主键的,需要和权限分配表(DISP)相连接才可以获得账号级别的信息。然后提取借款人居住地情况,需要连接地区表(district)。第三步提取行为信息:账户平均余额、余额的标准差、变异系数、平均入账和平均支出的比例、贷存比等。
贷款(Loans)表中的还款状态(status)变量记录了客户的贷款偿还情况,其中A代表合同终止且正常还款,B代表合同终止但是未还款,C代表合同未结束且正常还款,D代表合同未结束但是已经拖欠贷款了。出现贷款拖欠则用1标识,如果始终没有出现违约,则设置为0。显然,响应变量即还款状态为二分类变量,因此选择分类模型中最常使用的算法逻辑回归模型建模。
#数据导入 loan<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/loans.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") account<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/accounts.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") card<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/card.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") client<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/clients.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") disp<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/disp.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") district<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/district.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") trans<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/trans.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") order<-read.csv("/Users/linda/Desktop/predict-loan-defaulters/order.csv",header = TRUE,stringsAsFactors = F,fileEncoding="GBK") ##数据转化 account$date<-as.Date(account$date) card$issued<-as.Date(card$issued) card$type<-as.factor(card$type) client$sex<-as.factor(client$sex) client$birth_date<-as.Date(client$birth_date) disp$type<-as.factor(disp$type) loan$date<-as.Date(loan$date) loan$status<-as.factor(loan$status) trans$date<-as.Date(trans$date) #去掉trans表格的千分位和美元符号,然后转化成数值类型 #install.packages('https://cran.rstudio.com/bin/macosx/el-capitan/contrib/3.6/stringr_1.4.0.tgz',repos = NULL) library(stringr) class(trans$amount) class(trans$balance) str(loan) trans$balance<-gsub(",","",trans$balance) trans$amount<-gsub(",","",trans$amount) trans$amount<-as.numeric(gsub("\\$","",trans$amount)) trans$balance<-as.numeric(gsub("\\$","",trans$balance)) #有数据框结构可知贷款状态有A、B、C、D共四种,分别数字化赋值 loan$new_status[loan$status=='A']<-'0' loan$new_status[loan$status=='B']<-'1' loan$new_status[loan$status=='C']<-'2' loan$new_status[loan$status=='D']<-'1' loan$new_status<-as.factor(loan$new_status) #根据不同表格的字段对应关系进行合并 data=merge(loan,disp,by.x = "account_id",by.y = "account_id",all.x = TRUE) data=data[data$type=="所有者",] #只有所有者才有权限进行贷款 data=merge(data,client,by.x = "client_id",by.y = "client_id",all.x = TRUE) data=merge(data,district,by.x="district_id",by.y = "A1",all.x = TRUE) data_temp=merge(loan,trans,by.x = "account_id",by.y = "account_id",all=FALSE) #data_temp的date.x指loan中贷款日期,date.y指trans的交易日期 #取一年的交易数据,评估贷款日期前365天至贷款日期前一天的交易数据 data_temp=data_temp[data_temp$date.x>data_temp$date.y&data_temp$date.x<data_temp$date.y+365,] #计算每个贷款账户贷款前一年的平均账户余额(财富水平)、余额的标准差(财富稳定程度)和变异系数(财富的相对稳定程度) mean=aggregate(data_temp[,14],by=list(data_temp[,1]),mean) sd=aggregate(data_temp[,14],by=list(data_temp[,1]),sd) names(mean)=c("account_id","mean") names(sd)=c("account_id","sd") data_temp1<-merge(mean,sd,by.x = "account_id",by.y = "account_id",all = TRUE) data_temp1$cv<-data_temp1$sd/data_temp1$mean #分别计算平均入账和平均支出及支出占收入的比例 amount<-aggregate(data_temp[,13],by=list(data_temp[,1],data_temp[,11]),sum) #根据账户ID和借贷类型分别汇总同一个账户的入账金额和支出金额 names(amount)<-c("account_id","type","amount") unique(amount$type) pay<-amount[amount$type=="借",] income<-amount[amount$type=="贷",] colnames(pay)<-c("account_id","type","pay") colnames(income)<-c("account_id","type","income") data_temp2<-merge(income,pay,by.x = "account_id",by.y = "account_id",all=TRUE)#得到每个账户ID下的还款总金额及借款金额总金额 #判断有无缺失值 unique(is.na(data_temp2$pay)) unique(is.na(data_temp2$income)) data_temp2[is.na(data_temp2$pay)==TRUE,5]=0 #计算支出占收入的比例 data_temp2$ratio<-data_temp2$pay/data_temp2$income #将平均帐户余额及其标准差和变异系数、平均入账和平均支出的比例与data数据表合并 data1<-merge(data,data_temp1,by.x="account_id",by.y="account_id",all=TRUE) data1<-merge(data1,data_temp2,by.x="account_id",by.y="account_id",all=TRUE) #计算贷存比、贷收比 data1$r_lb<-data1$amount/data1$mean data1$r_lincome<-data1$amount/data1$income head(data1$r_lb) head(data1$r_lincome) #缺失值处理 #判断缺失值个数,这里A12、A15、type.y存在缺失值 > sapply(data1, function(x) sum(is.na(x))) account_id district_id client_id loan_id date 0 0 0 0 0 amount duration payments status new_status 0 0 0 0 0 disp_id type sex birth_date GDP 0 0 0 0 0 A4 A10 A11 A12 A13 0 0 0 8 0 A14 A15 a16 mean sd 0 8 0 0 0 cv type.x income type.y pay 0 0 0 3 0 ratio r_lb r_lincome 0 0 0 #缺失值A12、A15用均值替代 data1$A12[is.na(data1$A12)] <- mean(data1$A12,na.rm=T) data1$A15[is.na(data1$A15)]<-mean(data1$A12,na.rm=T)
提取贷款状态为C(new_status为2)的用于预测,其他样本随机抽样,建立训练集和测试集。
data2<-data1[,c(6,7,10,15,16,17,18,19,20,21,22,23,24,25,26,28,30,31,32,33)] colnames(data2) data_model<-data2[data2$new_status!=2,] for_predict<-data2[data2$new_status==2,] #随机抽取模型数据集中70%的行数据作为训练集建立模型,剩余的数据作为测试数据 n<-nrow(data_model) rnd<-sample(n,n*.70) train<-data_model[rnd,] test<-data_model[-rnd,] ##使用向前逐步回归法进行逻辑回归建模 formula<new_status~GDP+A4+A10+A11+A12+amount+duration+A13+A14+A15+a16+mean+sd+cv+income+pay+r_lb+r_lincome+ratio model<-glm(formula,data = train,family = binomial(link = logit)) forward_model<-step(model,direction = "forward") summary(forward_model) ##使用向后逐步回归法进行逻辑回归建模 backward_model<-step(model,direction="backward") summary(backward_model) #逐步回归 both_model<-step(model,direction="both") summary(both_model)
三种回归模型结果如下:
1.向前回归
2.向后回归
3.逐步回归
从模型结果可知,上述三种方法的模型结果基本保持一致,三种方法预测的自变量A14(贷款者当地1000人中有多少企业家)、duration(贷款期限)、r_lb(申请贷款前一年的贷存比)、mean(平均存款余额)、 sd(存款余额的标准差)、ratio(支出占收入的比重)均是显著的,且回归系数的正负号均符合预期。其中,申请贷款前一年的贷存比、存款余额的标准差、贷款期限与违约正相关。存款余额的均值、贷款者当地1000人中有多少企业家与违约负相关。
用测试数据(test)做模型效果评估,以下选用逐步回归模型作为预测模型。通过计算准确率和ROC曲线下面积(AUC)来评估模型效果。
#用测试集做模型评估 pre<-predict(both_model,test,type = "response") #在预测数据集中,响应变量为1的概率大于0.5则认为违约,记为1,小于0.5为不违约,记为0。 test$pre_new_status<-ifelse(pre>0.5,1,0) table(test$new_status,test$pre_new_status) #准确率计算, #sum_diag表示对角线元素和即test数据集的实际值与预测值相一致的总个数 sum_diag<-sum(diag(table(test$new_status,test$pre_new_status))) sum<-sum(table(test$new_status,test$pre_new_status)) accuracy<-sum_diag/sum accuracy #计算出准确率85% #ROC曲线评估 #install.packages("/Users/linda/Downloads/sjmisc_2.8.3.tgz",repos = NULL) library(sjmisc) #install.packages("/Users/linda/Downloads/pROC_1.16.1.tgz",repos = NULL) library(pROC) roc_curve<-roc(test$new_status~pre) x<-1-roc_curve$specificities y<-roc_curve$sensitivities plot(x=x,y=y,xlim=c(0,1),ylim=c(0,1),xlab = '1-specificity',ylab = 'Sensitivity',main='ROC Curve',type='l',lwd=2.5) abline(a=0,b=1,col='black') auc<-roc_curve$auc text(0.5,0.4,paste('AUC:',round(auc,digits = 2)),col='red')
可以看到模型的准确率为85%,模型的ROC曲线非常接近左上角,其曲线下面积(AUC)为0.87,这说明模型的分类能力较强。
我们可以通过该模型得到每笔贷款的违约预测概率,根据概率可以知道这些贷款客户中哪些人的违约可能性较高,需要业务人员重点关注,提前想出应对措施。
#模型预测及应用
for_predict$predict<-predict(both_model,for_predict,type="response")
View(for_predict)
部分预测结果如图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。