Python計算woe和iv值


計算邏輯

先計算WOE值,再計算IV值。

其中Y或N分別是YES,NO,反應在因變量中,就是1和0。

  • Yi是第i組中1的個數,YT是所有(Total)為1的個數。
  • Ni是第i組中0的個數,NT是所有(Total)為0的個數。

舉例

數據如下,x分別取1-9,y對應是1和0。

x,y
1,1
2,1
3,0
4,1
5,1
6,0
7,0
8,0
9,1

如果對於x這9行數據分成三組:

  • 第0組:x=1,2,3
  • 第1組:x=4,5,6
  • 第2組:x=7,8,9

則第0組的WEO值計算過程如下。

  • Y0=2,因為分組內當x=1,2的時候y是1,共兩個1,則是2.
  • YT=5,因為y這一列總共有5個1。
  • N0=1,因為分組內當x=3的時候y是0,共1個1,則是1.
  • NT=4,因為y這一列有4個0.
WOE_0
=ln((2/5)/(1/4))
=ln(0.4/0.25)
=ln(1.6)
=0.47

有了WOE,開始計算IV:

IV_0
=(2/5-1/4)*WOE_0
=0.15*0.47
=0.0705

於是可計算出IV_0=0.0705。 同理可計算出IV_1= 0.070501, IV_2=0.274887。 則該X的iv即 iv=iv_0+iv_2+iv_3=0.415888

Python代碼

import pandas as pd
import numpy as np
def iv_woe(data:pd.DataFrame, target:str, bins:int = 10) -> (pd.DataFrame, pd.DataFrame):
    """計算woe和IV值
    
    參數:
    - data: dataframe數據
    - target: y列的名稱
    - bins: 分箱數(默認是10)
    """
    newDF,woeDF = pd.DataFrame(), pd.DataFrame()
    cols = data.columns
    for ivars in cols[~cols.isin([target])]:
        # 數據類型在bifc中、且數據>10則分箱
        if (data[ivars].dtype.kind in 'bifc') and (len(np.unique(data[ivars]))>10):
            binned_x = pd.qcut(data[ivars], bins,  duplicates='drop')
            d0 = pd.DataFrame({'x': binned_x, 'y': data[target]})
        else:
            d0 = pd.DataFrame({'x': data[ivars], 'y': data[target]})
        d = d0.groupby("x", as_index=False).agg({"y": ["count", "sum"]})
        d.columns = ['Cutoff', 'N', 'Events']
        d['% of Events'] = np.maximum(d['Events'], 0.5) / d['Events'].sum()
        d['Non-Events'] = d['N'] - d['Events']
        d['% of Non-Events'] = np.maximum(d['Non-Events'], 0.5) / d['Non-Events'].sum()
        d['WoE'] = np.log(d['% of Events']/d['% of Non-Events'])
        d['IV'] = d['WoE'] * (d['% of Events'] - d['% of Non-Events'])
        d.insert(loc=0, column='Variable', value=ivars)
        print("Information value of " + ivars + " is " + str(round(d['IV'].sum(),6)))
        temp =pd.DataFrame({"Variable" : [ivars], "IV" : [d['IV'].sum()]}, columns = ["Variable", "IV"])
        newDF=pd.concat([newDF,temp], axis=0)
        woeDF=pd.concat([woeDF,d], axis=0)
    return newDF, woeDF

調用

mydata = pd.read_csv("./data.csv",encoding='utf8')
newDF,woeDF=iv_woe(mydata,'y')

即可得到。注意,此處默認10組,上例中的x值是0-10,不足以分10組,則每個值為一組。注意其中的if判斷語句


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM