使用R建立银行贷款违约模型

一、项目背景及目的

 使用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)

部分预测结果如图:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值