使用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 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
三种回归模型结果如下:
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)