前面已經有了一篇信用卡的文章,拓展不同方法
前面的處理方式都一樣,主要不同的是從缺失值開始的:
#導入模塊 import pandas as pd import numpy as np from scipy import stats import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline plt.rc("font",family="SimHei",size="12") #解決中文無法顯示的問題 #導入數據 train=pd.read_csv('F:\\python\\Give-me-some-credit-master\\data\\cs-training.csv') #簡單查看數據 train.info() #頭三行和尾三行數據查看 b=train.head(3).append(train.tail(3)) #shape train.shape #(150000, 11) #將各英文字段轉為中文字段名方便理解 states={'Unnamed: 0':'id', 'SeriousDlqin2yrs':'好壞客戶', 'RevolvingUtilizationOfUnsecuredLines':'可用額度比值', 'age':'年齡', 'NumberOfTime30-59DaysPastDueNotWorse':'逾期30-59天筆數', 'DebtRatio':'負債率', 'MonthlyIncome':'月收入', 'NumberOfOpenCreditLinesAndLoans':'信貸數量', 'NumberOfTimes90DaysLate':'逾期90天筆數', 'NumberRealEstateLoansOrLines':'固定資產貸款量', 'NumberOfTime60-89DaysPastDueNotWorse':'逾期60-89天筆數', 'NumberOfDependents':'家屬數量'} train.rename(columns=states,inplace=True) #設置索引 train=train.set_index('id',drop=True) #描述性統計 train.describe() #查看每列缺失情況 train.isnull().sum() #查看缺失占比情況 train.isnull().sum()/len(train) #缺失值可視化 missing=train.isnull().sum() missing[missing>0].sort_values().plot.bar() #將大於0的拿出來並排序
首先復制一份新的數據
###3#3#下面的是缺失值的處理 #保留原數據 train_2=train.copy()
3.1缺失值處理
這種情況在現實問題中非常普遍,這會導致一些不能處理缺失值的分析方法無法應用,因此,在信用風險評級模型開發的第一步我們就要進行缺失值處理。缺失值處理的方法,包括如下幾種。
(1) 直接刪除含有缺失值的樣本。
(2) 根據樣本之間的相似性填補缺失值。
(3) 根據變量之間的相關關系填補缺失值。
變量MonthlyIncome缺失率比較大,所以我們根據變量之間的相關關系填補缺失值,我們采用隨機森林法:
(2) 根據樣本之間的相似性填補缺失值。
(3) 根據變量之間的相關關系填補缺失值。
變量MonthlyIncome缺失率比較大,所以我們根據變量之間的相關關系填補缺失值,我們采用隨機森林法:
NumberOfDependents變量缺失值比較少,直接刪除,對總體模型不會造成太大影響。對缺失值處理完之后,刪除重復項。
import pandas as pd import matplotlib.pyplot as plt #導入圖像庫 from sklearn.ensemble import RandomForestRegressor # 用隨機森林對缺失值預測填充函數 def set_missing(df): # 把已有的數值型特征取出來,由於家庭數量有缺失,就不包括這個,順便排列一下順序,將月收入放在第一位 process_df = df.ix[:,[5,0,1,2,3,4,6,7,8,9]] # 分成已知該特征和未知該特征兩部分,分為有缺失值的行和沒有缺失的行 known = process_df[process_df['月收入'].notnull()].as_matrix() unknown = process_df[process_df['月收入'].isnull()].as_matrix() # X為特征屬性值 X = known[:, 1:] # y為結果標簽值 y = known[:, 0] # fit到RandomForestRegressor之中 rfr = RandomForestRegressor(random_state=0, n_estimators=200,max_depth=3,n_jobs=-1) rfr.fit(X,y) # 用得到的模型進行未知特征值預測 predicted = rfr.predict(unknown[:, 1:]).round(0) #.round(0)是不保留小數點 print(predicted) # 用得到的預測結果填補原缺失數據 df.loc[(process_df['月收入'].isnull()), '月收入'] = predicted #loc的布爾索引,有空值的行對應的月收入的值用與預測值填補 return df if __name__ == '__main__': #載入數據 #train_2 = pd.read_csv('cs-training.csv') #數據集確實和分布情況 train_2.describe().to_csv('train_2Describe.csv')#了解數據集的分布情況 train_2=set_missing(train_2)#用隨機森林填補比較多的缺失值 train_2=train_2.dropna()#刪除比較少的缺失值 train_2 = train_2.drop_duplicates()#刪除重復項 train_2.to_csv('Missingtrain_2.csv',index=False) train_2.describe().to_csv('Missingtrain_2Describe.csv') ''' #異常值處理 #年齡等於0的異常值進行剔除 train_2=train_2[train_2['年齡']>0] # 箱形圖 train_2379=train_2[['逾期30-59天筆數','逾期90天筆數','逾期60-89天筆數']] train_2379.boxplot() train_2 = train_2[train_2['逾期30-59天筆數'] < 90] #因為剔除了這個,其余的兩個也會同事剔除 train_2379 = train_2[['逾期30-59天筆數', '逾期90天筆數', '逾期60-89天筆數']] train_2379.boxplot() plt.show() train_2.to_csv('Pretreatmenttrain_2.csv') '''
3.2異常值處理
缺失值處理完畢后,我們還需要進行異常值處理。異常值是指明顯偏離大多數抽樣數據的數值,找出樣本總體中的異常值,通常采用離群值檢測的方法。
數據集中好客戶為0,違約客戶為1,考慮到正常的理解,能正常履約並支付利息的客戶為1,所以我們將其取反。
年齡<0的去掉,那幾個逾期天數筆數的超離群點(>90)的也去掉
最后異常值的全部代碼如下
#數據切分和異常值處理和在一起 import pandas as pd import matplotlib.pyplot as plt #導入圖像庫 from sklearn.model_selection import train_test_split #異常值處理,通過箱型圖去將1.5倍1/4到3/4長度的值去掉 def outlier_processing(df,col): s=df[col] oneQuoter=s.quantile(0.25) threeQuote=s.quantile(0.75) irq=threeQuote-oneQuoter min=oneQuoter-1.5*irq max=threeQuote+1.5*irq df=df[df[col]<=max] df=df[df[col]>=min] return df if __name__ == '__main__': data = pd.read_csv('Missingtrain_2.csv') # 年齡等於0的異常值進行剔除 data = data[data['年齡'] > 0] data = data[data['逾期30-59天筆數'] < 90]#剔除異常值 data['好壞客戶']=1-data['好壞客戶'] Y = data['好壞客戶'] X = data.ix[:, 1:] X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=0) # print(Y_train) train = pd.concat([Y_train, X_train], axis=1) test = pd.concat([Y_test, X_test], axis=1) clasTest = test.groupby('好壞客戶')['好壞客戶'].count() train.to_csv('TrainData.csv',index=False) test.to_csv('TestData.csv',index=False) print(train.shape) print(test.shape)
四、探索性分析
在建立模型之前,我們一般會對現有的數據進行 探索性數據分析(Exploratory Data Analysis) 。 EDA是指對已有的數據(特別是調查或觀察得來的原始數據)在盡量少的先驗假定下進行探索。常用的探索性數據分析方法有:直方圖、散點圖和箱線圖等
這個數據我在第一篇文章寫得很清楚
五、變量選擇
特征變量選擇(排序)對於數據分析、機器學習從業者來說非常重要。好的特征選擇能夠提升模型的性能,更能幫助我們理解數據的特點、底層結構,這對進一步改善模型、算法都有着重要作用。至於Python的變量選擇代碼實現可以參考結合Scikit-learn介紹幾種常用的特征選擇方法。
在本文中,我們采用信用評分模型的變量選擇方法,通過WOE分析方法,即是通過比較指標分箱和對應分箱的違約概率來確定指標是否符合經濟意義。首先我們對變量進行離散化(分箱)處理。
在本文中,我們采用信用評分模型的變量選擇方法,通過WOE分析方法,即是通過比較指標分箱和對應分箱的違約概率來確定指標是否符合經濟意義。首先我們對變量進行離散化(分箱)處理。
5.1分箱處理
變量分箱(binning)是對連續變量離散化(discretization)的一種稱呼。信用評分卡開發中一般有常用的等距分段、等深分段、最優分段。其中等距分段(Equval length intervals)是指分段的區間是一致的,比如年齡以十年作為一個分段;等深分段(Equal frequency intervals)是先確定分段數量,然后令每個分段中數據數量大致相等;最優分段(Optimal Binning)又叫監督離散化(supervised discretizaion),使用遞歸划分(Recursive Partitioning)將連續變量分為分段,背后是一種基於條件推斷查找較佳分組的算法。
我們首先選擇對連續變量進行最優分段,在連續變量的分布不滿足最優分段的要求時,再考慮對連續變量進行等距分段。最優分箱的代碼如下:
我們首先選擇對連續變量進行最優分段,在連續變量的分布不滿足最優分段的要求時,再考慮對連續變量進行等距分段。最優分箱的代碼如下:
5.2woe
WoE分析, 是對指標分箱、計算各個檔位的WoE值並觀察WoE值隨指標變化的趨勢。其中WoE的數學定義是:
woe=ln(goodattribute/badattribute)
在進行分析時,我們需要對各指標從小到大排列,並計算出相應分檔的WoE值。其中正向指標越大,WoE值越小;反向指標越大,WoE值越大。正向指標的WoE值負斜率越大,反響指標的正斜率越大,則說明指標區分能力好。WoE值趨近於直線,則意味指標判斷能力較弱。若正向指標和WoE正相關趨勢、反向指標同WoE出現負相關趨勢,則說明此指標不符合經濟意義,則應當予以去除。
woe函數實現在上一節的mono_bin()函數里面已經包含,這里不再重復。
woe=ln(goodattribute/badattribute)
在進行分析時,我們需要對各指標從小到大排列,並計算出相應分檔的WoE值。其中正向指標越大,WoE值越小;反向指標越大,WoE值越大。正向指標的WoE值負斜率越大,反響指標的正斜率越大,則說明指標區分能力好。WoE值趨近於直線,則意味指標判斷能力較弱。若正向指標和WoE正相關趨勢、反向指標同WoE出現負相關趨勢,則說明此指標不符合經濟意義,則應當予以去除。
woe函數實現在上一節的mono_bin()函數里面已經包含,這里不再重復。
5.3相關性和iv值篩選
接下來,我們會用經過清洗后的數據看一下變量間的相關性。注意,這里的相關性分析只是初步的檢查,進一步檢查模型的VI(證據權重)作為變量篩選的依據。
相關性圖我們通過Python里面的seaborn包,調用heatmap()繪圖函數進行繪制,實現代碼如下:
相關性圖我們通過Python里面的seaborn包,調用heatmap()繪圖函數進行繪制,實現代碼如下:
IV指標是一般用來確定自變量的預測能力。 其公式為:
IV=sum((goodattribute-badattribute)*ln(goodattribute/badattribute))
通過IV值判斷變量預測能力的標准是:
< 0.02: unpredictive
0.02 to 0.1: weak
0.1 to 0.3: medium
0.3 to 0.5: strong
> 0.5: suspicious
IV=sum((goodattribute-badattribute)*ln(goodattribute/badattribute))
通過IV值判斷變量預測能力的標准是:
< 0.02: unpredictive
0.02 to 0.1: weak
0.1 to 0.3: medium
0.3 to 0.5: strong
> 0.5: suspicious
import pandas as pd import numpy as np from pandas import Series,DataFrame import scipy.stats.stats as stats import matplotlib.pyplot as plt import statsmodels.api as sm import math # 定義自動分箱函數,好用戶是1 def mono_bin(Y, X, n = 20): r = 0 good=Y.sum() #Y是標簽值,也就是好壞客戶,計算好用戶個數 bad=Y.count()-good #壞用戶個數 while np.abs(r) < 1: #np.abs(r)是求覺得值,有點疑惑,相關系數<1就一直減少分箱個數,感覺相關系數一直都是小於1 d1 = pd.DataFrame({"X": X, "Y": Y, "Bucket": pd.qcut(X, n)}) #等深分段,並且將XY和X分段好的數據組合成一個df d2 = d1.groupby('Bucket', as_index = True) #根據分箱的去分組,且不要索引 r, p = stats.spearmanr(d2.mean().X, d2.mean().Y) #斯皮爾曼等級相關系數 n = n - 1 d3 = pd.DataFrame(d2.X.min(), columns = ['min']) #最小值 d3['min']=d2.min().X #X的最小值 d3['max'] = d2.max().X #X的最大值 d3['sum'] = d2.sum().Y #好用戶個數 d3['total'] = d2.count().Y #全部用戶個數 d3['rate'] = d2.mean().Y #好用戶占比 d3['woe']=np.log((d3['rate']/(1-d3['rate']))/(good/bad)) #woe計算 d3['goodattribute']=d3['sum']/good #每個區間中好用戶占比 d3['badattribute']=(d3['total']-d3['sum'])/bad #每個區間中壞用戶占比 iv=((d3['goodattribute']-d3['badattribute'])*d3['woe']).sum() #iv值計算 d4 = (d3.sort_index(by = 'min')) print("=" * 60) print(d4) cut=[] cut.append(float('-inf')) #負無窮 for i in range(1,n+1): qua=X.quantile(i/(n+1)) cut.append(round(qua,4)) cut.append(float('inf')) woe=list(d4['woe'].round(3)) return d4,iv,cut,woe #自定義分箱函數 自定義分箱區間cat def self_bin(Y,X,cat): good=Y.sum() bad=Y.count()-good d1=pd.DataFrame({'X':X,'Y':Y,'Bucket':pd.cut(X,cat)}) d2=d1.groupby('Bucket', as_index = True) d3 = pd.DataFrame(d2.X.min(), columns=['min']) d3['min'] = d2.min().X d3['max'] = d2.max().X d3['sum'] = d2.sum().Y d3['total'] = d2.count().Y d3['rate'] = d2.mean().Y d3['woe'] = np.log((d3['rate'] / (1 - d3['rate'])) / (good / bad)) d3['goodattribute'] = d3['sum'] / good d3['badattribute'] = (d3['total'] - d3['sum']) / bad iv = ((d3['goodattribute'] - d3['badattribute']) * d3['woe']).sum() d4 = (d3.sort_index(by='min')) print("=" * 60) print(d4) woe = list(d4['woe'].round(3)) return d4, iv,woe #用woe代替 def replace_woe(series,cut,woe): list=[] i=0 while i<len(series): value=series[i] j=len(cut)-2 #減去收尾的正負無窮? 如果cut=6,j=4, m=len(cut)-2 while j>=0: if value>=cut[j]: #如果值大於正無窮前面的值到正無窮之間 j=-1 #j=3 else: j -=1 #否則j-1,m-1,相當於找到合適的區間 m -= 1 list.append(woe[m]) i += 1 return list #計算分數函數 def get_score(coe,woe,factor): scores=[] for w in woe: score=round(coe*w*factor,0) scores.append(score) return scores #根據變量計算分數 def compute_score(series,cut,score): list = [] i = 0 while i < len(series): value = series[i] j = len(cut) - 2 m = len(cut) - 2 while j >= 0: if value >= cut[j]: j = -1 else: j -= 1 m -= 1 list.append(score[m]) i += 1 return list if __name__ == '__main__': data = pd.read_csv('TrainData.csv') pinf = float('inf')#正無窮大 ninf = float('-inf')#負無窮大 dfx1, ivx1,cutx1,woex1=mono_bin(data['好壞客戶'],data['可用額度比值'],n=10) dfx2, ivx2,cutx2,woex2=mono_bin(data['好壞客戶'], data['年齡'], n=10) dfx4, ivx4,cutx4,woex4 =mono_bin(data['好壞客戶'], data['負債率'], n=20) dfx5, ivx5,cutx5,woex5 =mono_bin(data['好壞客戶'], data['月收入'], n=10) # 連續變量離散化 cutx3 = [ninf, 0, 1, 3, 5, pinf] cutx6 = [ninf, 1, 2, 3, 5, pinf] cutx7 = [ninf, 0, 1, 3, 5, pinf] cutx8 = [ninf, 0,1,2, 3, pinf] cutx9 = [ninf, 0, 1, 3, pinf] cutx10 = [ninf, 0, 1, 2, 3, 5, pinf] dfx3, ivx3,woex3 = self_bin(data['好壞客戶'], data['逾期30-59天筆數'], cutx3) dfx6, ivx6 ,woex6= self_bin(data['好壞客戶'], data['信貸數量'], cutx6) dfx7, ivx7,woex7 = self_bin(data['好壞客戶'], data['逾期90天筆數'], cutx7) dfx8, ivx8,woex8 = self_bin(data['好壞客戶'], data['固定資產貸款量'], cutx8) dfx9, ivx9,woex9 = self_bin(data['好壞客戶'], data['逾期60-89天筆數'], cutx9) dfx10, ivx10,woex10 = self_bin(data['好壞客戶'], data['家屬數量'], cutx10) ivlist=[ivx1,ivx2,ivx3,ivx4,ivx5,ivx6,ivx7,ivx8,ivx9,ivx10] index=['x1','x2','x3','x4','x5','x6','x7','x8','x9','x10'] fig1 = plt.figure(1) ax1 = fig1.add_subplot(1, 1, 1) x = np.arange(len(index))+1 ax1.bar(x, ivlist, width=0.4) ax1.set_xticks(x) ax1.set_xticklabels(index, rotation=0, fontsize=12) ax1.set_ylabel('IV(Information Value)', fontsize=14) for a, b in zip(x, ivlist): plt.text(a, b + 0.01, '%.4f' % b, ha='center', va='bottom', fontsize=10) # 替換成woe data['可用額度比值'] = Series(replace_woe(data['可用額度比值'], cutx1, woex1)) data['年齡'] = Series(replace_woe(data['年齡'], cutx2, woex2)) data['逾期30-59天筆數'] = Series(replace_woe(data['逾期30-59天筆數'], cutx3, woex3)) data['負債率'] = Series(replace_woe(data['負債率'], cutx4, woex4)) data['月收入'] = Series(replace_woe(data['月收入'], cutx5, woex5)) data['信貸數量'] = Series(replace_woe(data['信貸數量'], cutx6, woex6)) data['逾期90天筆數'] = Series(replace_woe(data['逾期90天筆數'], cutx7, woex7)) data['固定資產貸款量'] = Series(replace_woe(data['固定資產貸款量'], cutx8, woex8)) data['逾期60-89天筆數'] = Series(replace_woe(data['逾期60-89天筆數'], cutx9, woex9)) data['家屬數量'] = Series(replace_woe(data['家屬數量'], cutx10, woex10)) data.to_csv('WoeData.csv', index=False) test= pd.read_csv('TestData.csv') # 替換成woe test['可用額度比值'] = Series(replace_woe(test['可用額度比值'], cutx1, woex1)) test['年齡'] = Series(replace_woe(test['年齡'], cutx2, woex2)) test['逾期30-59天筆數'] = Series(replace_woe(test['逾期30-59天筆數'], cutx3, woex3)) test['負債率'] = Series(replace_woe(test['負債率'], cutx4, woex4)) test['月收入'] = Series(replace_woe(test['月收入'], cutx5, woex5)) test['信貸數量'] = Series(replace_woe(test['信貸數量'], cutx6, woex6)) test['逾期90天筆數'] = Series(replace_woe(test['逾期90天筆數'], cutx7, woex7)) test['固定資產貸款量'] = Series(replace_woe(test['固定資產貸款量'], cutx8, woex8)) test['逾期60-89天筆數'] = Series(replace_woe(test['逾期60-89天筆數'], cutx9, woex9)) test['家屬數量'] = Series(replace_woe(test['家屬數量'], cutx10, woex10)) test.to_csv('TestWoeData.csv', index=False) ''' #計算分數 #coe為邏輯回歸模型的系數 coe=[9.738849,0.638002,0.505995,1.032246,1.790041,1.131956] # 我們取600分為基礎分值,PDO為20(每高20分好壞比翻一倍),好壞比取20。 p = 20 / math.log(2) q = 600 - 20 * math.log(20) / math.log(2) baseScore = round(q + p * coe[0], 0) # 各項部分分數 x1 = get_score(coe[1], woex1, p) x2 = get_score(coe[2], woex2, p) x3 = get_score(coe[3], woex3, p) x7 = get_score(coe[4], woex7, p) x9 = get_score(coe[5], woex9, p) print(x1,x2, x3, x7, x9) test1 = pd.read_csv('TestData.csv') test1['BaseScore']=Series(np.zeros(len(test1)))+baseScore test1['x1'] = Series(compute_score(test1['可用額度比值'], cutx1, x1)) test1['x2'] = Series(compute_score(test1['年齡'], cutx2, x2)) test1['x3'] = Series(compute_score(test1['逾期30-59天筆數'], cutx3, x3)) test1['x7'] = Series(compute_score(test1['逾期90天筆數'], cutx7, x7)) test1['x9'] = Series(compute_score(test1['逾期60-89天筆數'], cutx9, x9)) test1['Score'] = test1['x1'] + test1['x2'] + test1['x3'] + test1['x7'] +test1['x9'] + baseScore test1.to_csv('ScoreData.csv', index=False) plt.show() '''
六、模型分析
證據權重(Weight of Evidence,WOE)轉換可以將Logistic回歸模型轉變為標准評分卡格式。引入WOE轉換的目的並不是為了提高模型質量,只是一些變量不應該被納入模型,這或者是因為它們不能增加模型值,或者是因為與其模型相關系數有關的誤差較大,其實建立標准信用評分卡也可以不采用WOE轉換。這種情況下,Logistic回歸模型需要處理更大數量的自變量。盡管這樣會增加建模程序的復雜性,但最終得到的評分卡都是一樣的。
在建立模型之前,我們需要將篩選后的變量轉換為WoE值,便於信用評分
在建立模型之前,我們需要將篩選后的變量轉換為WoE值,便於信用評分
6.1woe轉換
我們將每個變量都進行替換,並將其保存到WoeData.csv文件中
6.2Logisic模型建立
我們直接調用statsmodels包來實現邏輯回歸
6.3模型檢驗
到這里,我們的建模部分基本結束了。我們需要驗證一下模型的預測能力如何。我們使用在建模開始階段預留的test數據進行檢驗。通過ROC曲線和AUC來評估模型的擬合能力。
在Python中,可以利用sklearn.metrics,它能方便比較兩個分類器,自動計算ROC和AUC。
在Python中,可以利用sklearn.metrics,它能方便比較兩個分類器,自動計算ROC和AUC。
import pandas as pd import matplotlib.pyplot as plt #導入圖像庫 import matplotlib import seaborn as sns import statsmodels.api as sm from sklearn.metrics import roc_curve, auc if __name__ == '__main__': matplotlib.rcParams['axes.unicode_minus'] = False data = pd.read_csv('WoeData.csv') Y=data['好壞客戶'] X=data.drop(['好壞客戶','負債率','月收入', '信貸數量','固定資產貸款量','家屬數量'],axis=1) X1=sm.add_constant(X) #在X前加上一列常數1,方便做帶截距項的回歸 logit=sm.Logit(Y,X1) result=logit.fit() print(result.summary()) #我加入的 print(result.params) test = pd.read_csv('TestWoeData.csv') Y_test = test['好壞客戶'] X_test = test.drop(['好壞客戶', '負債率', '月收入', '信貸數量','固定資產貸款量', '家屬數量'], axis=1) X3 = sm.add_constant(X_test) resu = result.predict(X3) fpr, tpr, threshold = roc_curve(Y_test, resu) rocauc = auc(fpr, tpr) plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % rocauc) plt.legend(loc='lower right') plt.plot([0, 1], [0, 1], 'r--') plt.xlim([0, 1]) plt.ylim([0, 1]) plt.ylabel('真正率') plt.xlabel('假正率') plt.show()


七、信用評分
7.1評分標准
由此可知每個變量不同分段對應的分數是B、β、ω這三個值的乘積,其中β(特征權值系數coe)和ω(WOE值)在前面已知,所以只要知道了AB的值就可以給用戶打分了,這里要求AB的值要預先設定幾個閾值,
偏移量A=offset
比例因子B=factor
b=offset+factor*log(o)
b+p=offset+factor *log(2o)
由上面score=A-Bβ0,所以log(odds)=β0

#計算分數 #coe為邏輯回歸模型的系數 coe=[9.738849,0.638002,0.505995,1.032246,1.790041,1.131956] # 我們取600分為基礎分值,PDO為20(每高20分好壞比翻一倍),好壞比取20。 p = 20 / math.log(2) #factor = 20 / np.log(2) q = 600 - 20 * math.log(20) / math.log(2) #offset = 600 - 20 * np.log(20) / np.log(2) baseScore = round(q + p * coe[0], 0) #b=offset+factor*log(o)
各分段的分數計算:
#前面已經有了 def get_score(coe,woe,factor): scores=[] for w in woe: score=round(coe*w*factor,0) scores.append(score) return scores # 各項部分分數 x1 = get_score(coe[1], woex1, p) x2 = get_score(coe[2], woex2, p) x3 = get_score(coe[3], woex3, p) x7 = get_score(coe[4], woex7, p) x9 = get_score(coe[5], woex9, p) print(x1,x2, x3, x7, x9)

根據變量來計算分數:
首先分數剔除,和woe替換方法一致,然后哥哥分數相加,再加上基礎分
#根據變量計算分數 def compute_score(series,cut,score): list = [] i = 0 while i < len(series): value = series[i] j = len(cut) - 2 m = len(cut) - 2 while j >= 0: if value >= cut[j]: j = -1 else: j -= 1 m -= 1 list.append(score[m]) i += 1 return list test1 = pd.read_csv('TestData.csv') test1['BaseScore']=Series(np.zeros(len(test1)))+baseScore #生成一個長度測試集程度一樣的元素全部都是基礎分的數組 test1['x1'] = Series(compute_score(test1['可用額度比值'], cutx1, x1)) test1['x2'] = Series(compute_score(test1['年齡'], cutx2, x2)) test1['x3'] = Series(compute_score(test1['逾期30-59天筆數'], cutx3, x3)) test1['x7'] = Series(compute_score(test1['逾期90天筆數'], cutx7, x7)) test1['x9'] = Series(compute_score(test1['逾期60-89天筆數'], cutx9, x9)) test1['Score'] = test1['x1'] + test1['x2'] + test1['x3'] + test1['x7'] +test1['x9'] + baseScore test1.to_csv('ScoreData.csv', index=False) plt.show()
文章參考https://www.jianshu.com/p/159f381c661d
