信用評分卡建模分析-R語言
5 人贊了文章
1. 摘要
本文基於kaggle上Give Me Some Credit的數據,其主題是通過預測某人在未來兩年內將會經歷財務危機的可能性來提高信用評分的效果,幫助貸款人做出最好的決策。
本文將結合信用卡評分的構建原理,採用R語言完成數據的清洗和處理工作;利用邏輯回歸模型建立信用卡評分的基礎模型;通過變數的證據權重轉換(WOE)創建信用卡評分卡,並開發一個簡單的信用評分系統。
2. 背景
信用評分卡模型在國外是一種成熟的預測方法,尤其在信用風險評估以及金融風險控制領域更是得到了比較廣泛的使用,其原理是將模型變數WOE編碼方式離散化之後運用logistic回歸模型進行的一種二分類變數的廣義線性模型。
客戶評分卡由一系列用戶特徵項組成,。每一個特徵項都有一系列可能的屬性,例如,年齡、銀行流水、收入等。在開發評分卡系統模型中,先確定屬性與申請人未來信用表現之間的相互關係,然後給屬性分配適當的分數權重,分配的分數權重要反映這種相互關係。分數權重越大,說明該屬性表示的信用表現越好。一個申請的得分是其屬性分值的簡單求和。如果申請人的信用評分大於等於金融放款機構所設定的界限分數,此申請處於可接受的風險水平並將被批准;低於界限分數的申請人將被拒絕或給予標示以便進一步審查。
3.數據處理
3.1、數據來源
數據來自Kaggle的give me some credit項目,其中cs-training.csv是有15萬條的樣本數據,包含了12個變數,下圖可以看到這份數據的大致情況。下載地址為:https://www.kaggle.com/c/GiveMeSomeCredit/data
3.2、數據描述
數據屬於個人消費類貸款,只考慮評分卡最終實施時能夠使用到的數據應從如下一些方面獲取數據:
–基本屬性:包括了借款人當時的年齡。
–償債能力:包括了借款人的月收入、負債比率。
–信用往來:兩年內35-59天逾期次數、兩年內60-89天逾期次數、兩年內90天或高於90天逾期的次數。
–財產狀況:包括了開放式信貸和貸款數量、不動產貸款或額度數量。
–貸款屬性:暫無。
–其他因素:包括了借款人的家屬數量(不包括本人在內)。
具體情況如下圖
3.3、讀入數據
setwd("C:/Users/45147/Desktop/信用卡評分")traindata<-read.csv("cs-training.csv",header=T,stringsAsFactors=F)數據顯示的結構如下str(traindata)data.frame: 150000 obs. of 12 variables: $ X : int 1 2 3 4 5 6 7 8 9 10 ... $ SeriousDlqin2yrs : int 1 0 0 0 0 0 0 0 0 0 ... $ RevolvingUtilizationOfUnsecuredLines: num 0.766 0.957 0.658 0.234 0.907 ... $ age : int 45 40 38 30 49 74 57 39 27 57 ... $ NumberOfTime30.59DaysPastDueNotWorse: int 2 0 1 0 1 0 0 0 0 0 ... $ DebtRatio : num 0.803 0.1219 0.0851 0.036 0.0249 ... $ MonthlyIncome : int 9120 2600 3042 3300 63588 3500 NA 3500 NA 23684 ... $ NumberOfOpenCreditLinesAndLoans : int 13 4 2 5 7 3 8 8 2 9 ... $ NumberOfTimes90DaysLate : int 0 0 1 0 0 0 0 0 0 0 ... $ NumberRealEstateLoansOrLines : int 6 0 0 0 1 1 3 0 0 4 ...
3.4、更換變數名
首先去掉原數據中的順序變數,即第一列的id變數。由於要預測的是SeriousDlqin2yrs變數,因此將其設為響應變數y,其餘變數名較長,可分別設為x1~x10變數。
traindata<-traindata[-1]names(traindata)<-c("y","x1","x2","x3","x4","x5","x6","x7","x8","x9","x10")> head(traindata) y x1 x2 x3 x4 x5 x6 x7 x8 x9 x101 1 0.7661266 45 2 0.80298213 9120 13 0 6 0 22 0 0.9571510 40 0 0.12187620 2600 4 0 0 0 13 0 0.6581801 38 1 0.08511338 3042 2 1 0 0 04 0 0.2338098 30 0 0.03604968 3300 5 0 0 0 05 0 0.9072394 49 1 0.02492570 63588 7 0 1 0 06 0 0.2131787 74 0 0.37560697 3500 3 0 1 0 1
SeriousDlqin2yrs變數中1表示違約,0表示沒有違約,為了方便後續分析,使一個人的信用程度與其分數大小正相關,將y作變換,令0表示違約,1表示沒有違約。
3.5、缺失值處理
VIM包中的matrixplot函數可以直觀地展現數據中的缺失情況,其中紅色表示有缺失值,顏色越深表示值越大,可以看到x5變數和x10變數有缺失值,通過mice包中的md.pattern函數可以統計出各列缺失值大小,可以看到monthlyincome列共有缺失值29731個,numberofdependents有3924個。
matrixplot(traindata)
> md.pattern(traindata) y x1 x2 x3 x4 x6 x7 x8 x9 x10 x5 120269 1 1 1 1 1 1 1 1 1 1 1 0 25807 1 1 1 1 1 1 1 1 1 1 0 1 3924 1 1 1 1 1 1 1 1 1 0 0 2 0 0 0 0 0 0 0 0 0 3924 29731 33655
缺失值較多的x5列,所佔樣本比例較大,如果直接刪除可能導致結果受影響,可採用均值/中位數/眾數填補法,也可以採用knn插值法或樹填補法,考慮到x5分布規律呈偏正態分布,這裡用中位數插值法(用knn插值法最後做出來的結果相差並不大)。
#MonthlyIncome分布圖ggplot(data = traindata,aes(x5))+geom_density(fill="blue")+xlim(0,25000)+ geom_vline(aes(xintercept=median(traindata$x5[!is.na(traindata$x5)])),colour="red",linetype="dashed",lwd=1)
#中位數填充traindata$x5[is.na(traindata$x5)]=median(traindata$x5[!is.na(traindata$x5)])
對於缺失值不太多的x10列直接將缺失值刪除
traindata<-na.omit(traindata)
3.6、異常值處理
異常的值的檢測,常見的檢測方法有:單變數異常值檢測、LOF異常值檢測、聚類進行異常值的檢測。
3.6.1 age異常值處理
利用boxplot函數作出分布的箱線圖
boxplot(traindata$x2)
通過箱線圖可以看到,年齡的異常值集中在100附近,結合現實生活中信用卡的申請條件,申請人的年齡必須在18~65歲之間,因此將x2中小於18和大於65歲的數據進行刪除,並boxplot.stats()檢查刪除後的異常值為0。
traindata<-traindata[traindata$x2<=65&traindata$x2>=18,]> boxplot.stats(traindata$x2)$`stats`[1] 21 39 48 56 65$n[1] 119063$conf[1] 47.92216 48.07784$outinteger(0)
3.6.2 x3,x7,x9列的異常值處理
由下表可知:x3、x7、x9的異常值均為96、98,予以刪除。同時,刪除x3變數中的異常值之後,其餘兩個變數的異常值也相應被刪除。
boxplot(traindata$x3,traindata$x7,traindata$x9)
unique(traindata$x3)unique(traindata$x7)unique(traindata$x9)traindata<-traindata[-which(traindata$x3==96),]traindata<-traindata[-which(traindata$x3==98),]
4、數據建模
4.1、相關性分析
建模之前首先得檢驗變數之間的相關性,如果變數之間相關性顯著,會影響模型的預測效果。調用R語言中的cor()函數可以不同變數之間的相關係數,相關係數的符號表示關係的方向,正號表示正相關,符號表示負相關,其值的大小表示關係的強弱,完全不相關為0,完全相關為1。同時,調用corrplot包中的corrplot函數可以實現相關係數的可視化。
cor1<-cor(traindata)corrplot(cor1,method="number")
由上圖可以看出,各變數之間的相關性是非常小的。其實Logistic回歸同樣需要檢驗多重共線性問題,不過此處由於各變數之間的相關性較小,可以初步判斷不存在多重共線性問題,當然我們在建模後還可以用VIF(方差膨脹因子)來檢驗多重共線性問題。如果存在多重共線性,即有可能存在兩個變數高度相關,需要降維或剔除處理。
4.2 切分數據集
> table(traindata$y) 0 1 9044 109785
由上表可知:響應變數y存在著明顯的類失衡問題,y等於0的觀測值為9044,僅占所有觀測值的7.6%,因此,我們需要對非平衡數據進行處理,基於smote演算法,調用R語言中caret包中的createDataPartition對稀有數據進行超級採樣。
library(caret)set.seed(1234)splitIndex<-createDataPartition(traindata$y,time=1,p=0.5,list=FALSE)train<-traindata[splitIndex,]test<-traindata[-splitIndex,]> prop.table(table(train$y)) 0 1 0.07716907 0.92283093 > prop.table(table(test$y)) 0 1 0.07504965 0.92495035
由上表可知:兩者分類後的結果是平衡的,y等於1的概率均為7.6%左右,處於良好的水平,因此,可以採用切割後的數據進行建模和預測分析。
4.3、建模分析
Logistic回歸模型在信用卡評分開發的基礎模型,由於其自身的特點以及對自變數進行證據權重轉換(WOE),logistic回歸的結果可以直接轉換為一個匯總表,即所謂的標準評分卡格式。調用R語言中glm()函數對所有變數進行logistic回歸建模。
#建模fit<-glm(y~.,data=train,family=binomial())summary(fit)> summary(fit)Call:glm(formula = y ~ ., family = binomial(), data = train)Deviance Residuals: Min 1Q Median 3Q Max -2.9925 0.2570 0.3029 0.3566 4.6908 Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) 1.820e+00 7.398e-02 24.601 < 2e-16 ***x1 3.661e-05 8.493e-05 0.431 0.66641 x2 2.486e-02 1.660e-03 14.977 < 2e-16 ***x3 -5.587e-01 1.619e-02 -34.512 < 2e-16 ***x4 4.364e-05 1.759e-05 2.482 0.01308 * x5 2.302e-05 4.549e-06 5.059 4.21e-07 ***x6 1.234e-02 4.088e-03 3.018 0.00254 ** x7 -8.422e-01 2.489e-02 -33.840 < 2e-16 ***x8 -1.081e-01 1.602e-02 -6.752 1.46e-11 ***x9 -7.142e-01 3.333e-02 -21.431 < 2e-16 ***x10 -5.477e-02 1.407e-02 -3.893 9.89e-05 ***---Signif. codes: 0 『***』 0.001 『**』 0.01 『*』 0.05 『.』 0.1 『 』 1(Dispersion parameter for binomial family taken to be 1) Null deviance: 32298 on 59414 degrees of freedomResidual deviance: 26654 on 59404 degrees of freedomAIC: 26676Number of Fisher Scoring iterations: 6
由回歸結果可知,在利用所有變數進行logistic回歸時,變數x1、x4、x6對響應變數y的貢獻不顯著,因此,直接刪除變數x1、x4、x6,採用剩餘的變數進行logistic回歸。
fit2<-glm(y~x2+x3+x5+x7+x8+x9+x10,data=train,family=binomial())summary(fit2)> summary(fit2)Call:glm(formula = y ~ x2 + x3 + x5 + x7 + x8 + x9 + x10, family = binomial(), data = train)Deviance Residuals: Min 1Q Median 3Q Max -3.0004 0.2576 0.3036 0.3568 4.6944 Coefficients: Estimate Std. Error z value Pr(>|z|) (Intercept) 1.846e+00 7.358e-02 25.095 < 2e-16 ***x2 2.624e-02 1.626e-03 16.141 < 2e-16 ***x3 -5.508e-01 1.599e-02 -34.439 < 2e-16 ***x5 2.295e-05 4.484e-06 5.119 3.07e-07 ***x7 -8.559e-01 2.465e-02 -34.723 < 2e-16 ***x8 -8.248e-02 1.438e-02 -5.736 9.72e-09 ***x9 -7.168e-01 3.336e-02 -21.487 < 2e-16 ***x10 -5.689e-02 1.400e-02 -4.064 4.82e-05 ***---Signif. codes: 0 『***』 0.001 『**』 0.01 『*』 0.05 『.』 0.1 『 』 1(Dispersion parameter for binomial family taken to be 1) Null deviance: 32298 on 59414 degrees of freedomResidual deviance: 26670 on 59407 degrees of freedomAIC: 26686Number of Fisher Scoring iterations: 6
由上表可知:第二個回歸模型所有的變數都通過了檢驗,且AIC值更小,所以特徵變數選擇:x2+x3+x5+x7+x8+x9+x10。
4.4、模型評估
通常一個二值分類器可以通過ROC(Receiver Operating Characteristic)曲線和AUC值來評價優劣。
很多二元分類器會產生一個概率預測值,而非僅僅是0-1預測值。我們可以使用某個臨界點(例如0.5),以劃分哪些預測為1,哪些預測為0。得到二元預測值後,可以構建一個混淆矩陣來評價二元分類器的預測效果。所有的訓練數據都會落入這個矩陣中,而對角線上的數字代表了預測正確的數目,即true positive + true nagetive。同時可以相應算出TPR(真正率或稱為靈敏度)和TNR(真負率或稱為特異度)。我們主觀上希望這兩個指標越大越好,但可惜二者是一個此消彼漲的關係。除了分類器的訓練參數,臨界點的選擇,也會大大的影響TPR和TNR。有時可以根據具體問題和需要,來選擇具體的臨界點。
如果我們選擇一系列的臨界點,就會得到一系列的TPR和TNR,將這些值對應的點連接起來,就構成了ROC曲線。ROC曲線可以幫助我們清楚的了解到這個分類器的性能表現,還能方便比較不同分類器的性能。在繪製ROC曲線的時候,習慣上是使用1-TNR作為橫坐標即FPR(false positive rate),TPR作為縱坐標。這是就形成了ROC曲線。
而AUC(Area Under Curve)被定義為ROC曲線下的面積,顯然這個面積的數值不會大於1。又由於ROC曲線一般都處於y=x這條直線的上方,所以AUC的取值範圍在0.5和1之間。使用AUC值作為評價標準是因為很多時候ROC曲線並不能清晰的說明哪個分類器的效果更好,而作為一個數值,對應AUC更大的分類器效果更好。
調用R語言中pROC包中的roc函數計算分類器的AUC值,可以方便的比較兩個分類器,並且自動標註出最優的臨界點。如下圖所示:最優點FPR=1-TNR=0.826,TPR=0.657,AUC值為0.803,說明該模型的預測效果不錯,正確率較高。
pre<-predict(fit2,newdata=test,type=response)library(pROC)modelroc<-roc(test$y,pre)plot(modelroc, print.auc=TRUE, auc.polygon=TRUE, grid=c(0.1, 0.2), grid.col=c("green", "red"), max.auc.polygon=TRUE,auc.polygon.col="skyblue", print.thres=TRUE)
5、WOE轉換
證據權重(Weight of Evidence,WOE)轉換可以將Logistic回歸模型轉化為標準評分卡格式,引入WOE轉換的目的並不是為了提高模型質量,而是由於一些變數不應該被納入模型,或者是因為它們不能增加模型值,或者是因為與其模型相關係數有關的誤差較大,其實建立標準信用評分卡也可以不採用WOE轉換。這種情況下,Logistic回歸模型需要處理更大數量的自變數。儘管這樣會增加建模程序的複雜性,但最終得到的評分卡都是一樣的。
用WOE(x)替換變數x,WOE()=ln[(違約/總違約)/(正常/總正常)]。由於模型中剔除x1,x4,x6三個變數,因此對剩下的變數進行WOE轉換。
5.1 數據分箱
x2變數
#age分箱cutx2=c(-Inf,25,30,35,40,45,50,55,60,65)plot(cut(traindata$x2,cutx2))
x3 變數
#x3分箱cutx3=c(-Inf,0,1,3,5,Inf)plot(cut(traindata$x3,cutx3))
x5變數
#x5月收入分箱cutx5=c(-Inf,2000,3000,4000,5000,6000,7500,9500,12000,Inf)plot(cut(traindata$x5,cutx5))
x7分箱
cutx7=c(-Inf,0,1,3,5,Inf)plot(cut(traindata$x7,cutx7))
x8分箱
#x8分箱cutx8= c(-Inf,0,1,2,3,5,Inf)plot(cut(traindata$x8,cutx8))
x9分箱
#x9分箱cutx9 = c(-Inf,0,1,3,5,Inf)plot(cut(traindata$x9,cutx9))
x10分箱
#x10分箱cutx10 = c(-Inf,0,1,2,3,5,Inf)plot(cut(traindata$x10,cutx10))
5.2 WOE計算
自定義getwoe函數求WOE值
#計算WOE值totalgood=as.numeric(table(traindata$y))[2]totalbad=as.numeric(table(traindata$y))[1]getwoe=function(a,p,q){ good=as.numeric(table(traindata$y[a>p&a<=q]))[2] bad=as.numeric(table(traindata$y[a>p&a<=q]))[1] woe=log((bad/totalbad)/(good/totalgood),base = exp(1)) return(woe)}#變數x2的woeagelessthan30=getwoe(traindata$x2,-Inf,30)age30to40=getwoe(traindata$x2,30,40)age40to50=getwoe(traindata$x2,40,50)age50to60=getwoe(traindata$x2,50,60)age60to65=getwoe(traindata$x2,60,65)age.woe=c(agelessthan30,age30to40,age40to50,age50to60,age60to65)age.woe> age.woe[1] -0.42500327 -0.27149880 -0.08269126 0.23391995 0.68770576
同理可求得x3、x5、x7、x8、x9、x10的WOE值,代碼略。
> x3.woe[1] 0.515650 -0.824714 -1.631922 -2.257530 -2.553581> monthincome.woe[1] -0.22434219 -0.40563193 -0.30965223 -0.17944094 0.04285133 0.14508656 0.33356138 0.50853497 0.50415145> x7_woe[1] 0.3779233 -1.8642639 -2.5833487 -3.1784788> x8_woe[1] -0.3186489 0.2684772 0.2566251 0.1029852 -0.3396567 -1.0471902> x9_woe[1] 0.2714411 -1.7222377 -2.5729789 -2.9590459 -3.2436368> x10_woe[1] 0.09959189 -0.06705405 -0.07731504 -0.16338771 -0.31096262 -0.54103346
5.3 對變數進行WOE轉換
#x2tem.age=0for(i in 1:nrow(traindata)){ if(traindata$x2[i]<=30) tem.age[i]=agelessthan30 else if(traindata$x2[i]<=40) tem.age[i]=age30to40 else if(traindata$x2[i]>40&&traindata$x2[i]<=50) tem.age[i]=age40to50 else if(traindata$x2[i]<50&&traindata$x2[i]<=60) tem.age[i]=age50to60 else tem.age[i]=age60to65}> table(tem.age)tem.age -0.425003273466751 -0.271498802932835 -0.0826912609511332 0.687705758479994 10205 24012 34603 50009
同理可將x3、x5、x7、x8、x9、x10的值分別轉換為對應的WOE值。
> table(tem.x3)tem.x3 -2.55358076714553 -2.25753044502323 -1.63192156345769 -0.824714008708016 0.515649994266875 210 1001 5722 13951 97945 210 > table(tem.x5)tem.x5-0.405631933817086 -0.309652233873216 -0.224342186261936 -0.179440944259881 0.0428513336679746 0.145086558807487 10355 12383 9651 12605 29993 13125 0.333561380297155 0.504151454222959 0.5085349728576 12113 9346 9258 > table(tem.x7)tem.x7-3.17847884717136 -3.14772242393002 -2.583348692666 -1.86426390130685 0.377923345255428 405 178 2049 4700 111497 405 > table(tem.x8)tem.x8 -1.04719016091769 -0.339656728191198 -0.318648911951698 0.102985216705541 0.25662505022848 0.268477202276241 668 2459 40810 5392 27222 42278 2459 668 > table(tem.x9)tem.x9 -3.2436367551358 -2.95904587525369 -2.57297885200258 -1.72223765222803 0.271441087493707 28 132 1333 5143 112193 28 > table(tem.x10)tem.x10 -0.54103346029572 -0.310962617548944 -0.163387714709247 -0.0773150420609804 -0.0670540541447507 0.0995918901363515 242 3572 9364 18990 22406 64255
6. 創建和實施評分卡
6.1 評分卡創建原理
標準評分卡採用的格式是評分卡中的每一個變數都遵循一系列IF-THEN法則,變數的值決定了該變數所分配的分值,總分就是各變數分值的和。
評分卡設定的分值刻度可以通過將分值表示為比率對數的現行表達式來定義。公式如下:
score總=A+B?ln(odds), odds=p/(1-p)
知道線性表達式的兩個參數A,B後就可以求每條記錄(申請人)的分值。為了求得A,B,需要設定兩個假設(分數的給定,很主觀)。
通俗來說就是,評分需要自己預設一個閥值,比如:
這個人預測出來「不發生違約」的幾率為0.8,設定這個人為500分;
另一個人預測出來「不發生違約」的幾率為0.9,設定這個人為600分。
閥值的設定需根據行業經驗不斷跟蹤調整,下面的分數設定僅代表假設。假設按好壞比為15時評分為600,每高20分時好壞比翻一倍,則有下列公式:
600=A+Bln(15)
620=A+Bln(30)
B<-20/(log(30,base = exp(1))-log(15,base=exp(1)))A<-600-B*log(15,base=exp(1))BA> B[1] 28.8539> A[1] 521.8622
6.2 對變數打分
#創建新的回歸模型fit3<-glm(y~.,data=trainwoe,family="binomial")summary(fit3)coe<-fit3$coefficients
信用卡評分的基礎分:
basescore<-A+B*as.numeric(coe[1])basescore<-round(basescore,0)> basescore[1]592
對各變數打分:
#構造計算分值函數getscore=function(i,x){ score=round(B*as.numeric(coe[i])*x,0) return(score)}
變數x2打分:
#變數x2打分> Agelessthan30.SCORE = getscore(2,agelessthan30)> Age30to40.SCORE = getscore(2,age30to40)> Age40to50.SCORE = getscore(2,age40to50)> Age50to60.SCORE = getscore(2,age50to60)> Age60to65.SCORE = getscore(2,age60to65)> Age.SCORE = c(Agelessthan30.SCORE,Age30to40.SCORE,Age40to50.SCORE,Age50to60.SCORE,Age60to65.SCORE)> Age.SCORE[1]-5 -3 -1 3 8
同理,x3、x5、x7、x8、x9、x10的分數為:
> x3.score[1] 10 -16 -33 -45 -51> monthincome.score[1] -3 -6 -4 -3 1 2 5 7 7> x7_score[1] 7 -37 -51 -63 -62> x8_score[1] -5 5 4 2 -6 -18> x9_score[1] 4 -24 -36 -41 -45> x10_score[1] 2 -1 -2 -4 -7 -12
最終得到評分卡如下:
一個實例:
7. 建立自動評分系統
基於創建的評分卡,建立信用卡自動評分系統,具體如下所示:
#建立自動評分系統#x2變數score.x2=0for(i in 1:nrow(traindata)){ if(traindata$x2[i]<=30) score.x2[i]=Agelessthan30.SCORE else if(traindata$x2[i]<=40) score.x2[i]=Age30to40.SCORE else if(traindata$x2[i]<=50) score.x2[i]=Age40to50.SCORE else if(traindata$x2[i]<=60) score.x2[i]=Age50to60.SCORE else score.x2[i]=Age60to65.SCORE}table(score.x2) #變數x3score.x3=0for(i in 1:nrow(traindata)){ if(traindata$x3[i]<=0) score.x3[i]=x3lessthan0.score else if(traindata$x3[i]<=1) score.x3[i]=x30to1.score else if(traindata$x3[i]<=3) score.x3[i]=x31to3.score else if(traindata$x3[i]<=5) score.x3[i]=x33to5.score else score.x3[i]=x3morehtan5.score}table(score.x3) #變數x5score.x5=0for(i in 1: nrow(traindata)){ if(traindata$x5[i]<=2000) score.x5[i]=monthincomelessthan2000.score else if(traindata$x5[i]<=3000) score.x5[i]=month2000to3000.score else if(traindata$x5[i]<=4000) score.x5[i]=month3000to4000.score else if(traindata$x5[i]<=5000) score.x5[i]=month4000to5000.score else if(traindata$x5[i]<=6000) score.x5[i]=month5000to6000.score else if(traindata$x5[i]<=7500) score.x5[i]=month6000to7500.score else if(traindata$x5[i]<=9500) score.x5[i]=month7500to9500.score else if(traindata$x5[i]<=12000) score.x5[i]=month9500to12000.score else score.x5[i]=monthincomemorethan12000.score}table(score.x5) #變數x7score.x7=0for(i in 1:nrow(traindata)){ if(traindata$x7[i]<=0) score.x7[i]=x7_lessthan0.score else if(traindata$x7[i]<=1) score.x7[i]= x7_0to1.score else if(traindata$x7[i]<=3) score.x7[i]=x7_1to3.score else if(traindata$x7[i]<=5) score.x7[i]=x7_3to5.score else score.x7[i]=x7_morethan5.score}table(score.x7) #變數x8score.x8=0for(i in 1:nrow(traindata)){ if(traindata$x8[i]<=0) score.x8[i]=x8_lessthan0.score else if(traindata$x8[i]<=1) score.x8[i]= x8_0to1.score else if(traindata$x8[i]<=2) score.x8[i]= x8_1to2.score else if(traindata$x8[i]<=3) score.x8[i]=x8_2to3.score else if(traindata$x8[i]<=5) score.x8[i]=x8_3to5.score else score.x8[i]=x8_morethan5.score}table(score.x8) #變數x9score.x9=0for(i in 1:nrow(traindata)){ if(traindata$x9[i]<=0) score.x9[i]=x9_lessthan0.score else if(traindata$x9[i]<=1) score.x9[i]= x9_0to1.score else if(traindata$x9[i]<=3) score.x9[i]=x9_1to3.score else if(traindata$x9[i]<=5) score.x9[i]=x9_3to5.score else score.x9[i]=x9_morethan5.score}table(score.x9) #變數x10score.x10=0for(i in 1:nrow(traindata)){ if(traindata$x10[i]<=0) score.x10[i]=x10_lessthan0.score else if(traindata$x10[i]<=1) score.x10[i]= x10_0to1.score else if(traindata$x10[i]<=2) score.x10[i]= x10_1to2.score else if(traindata$x10[i]<=3) score.x10[i]=x10_2to3.score else if(traindata$x10[i]<=5) score.x10[i]=x10_3to5.score else score.x10[i]=x10_morethan5.score}table(score.x10) #創建自動評分卡系統creditScore=0for(i in 1:nrow(traindata)){ creditScore[i]=score.x2[i]+score.x3[i]+score.x5[i]+score.x7[i]+score.x8[i]+score.x9[i]+score.x10[i]+basescore}traindata$creditScore=round(creditScore,0)
綜合得分如圖
> head(traindata) y x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 creditScore1 0 0.7661266 45 2 8.029821e-01 9120 13 0 6 0 2 5542 1 0.9571510 40 0 1.218762e-01 2600 4 0 0 0 1 5983 1 0.6581801 38 1 8.511338e-02 3042 2 1 0 0 0 5334 1 0.2338098 30 0 3.604968e-02 3300 5 0 0 0 0 6015 1 0.9072394 49 1 2.492570e-02 63588 7 0 1 0 0 6007 1 0.3056825 57 0 5.710000e+03 5400 8 0 3 0 0 621
8. 結論
通過本文的學習系統的掌握了信用卡評分的原理和R語言中的logistic回歸模型,以及針對不平衡分類的數據切分及評價方法。同時,發現數據分箱對信用卡評分的影響比較大,合理的數據分箱是保證信用卡評分準確性的一個關鍵點。
參考:信用卡評分建模分析
推薦閱讀:
※營銷已死,增長為王(下)|一森管理案例之數據時代
※講講數據分析
※SQL初級數據分析(基於Microsoft Access)
※分析推特上狗狗的評分
※(7)Python初入坑之pandas基礎實操六
TAG:數據分析 |