【算法竞赛学习】金融风控之贷款违约预测-数据分析
Task2 數據分析
此部分為零基礎入門金融風控的 Task2 數據分析部分,帶你來了解數據,熟悉數據,為后續的特征工程做準備,歡迎大家后續多多交流。
賽題:零基礎入門數據挖掘 - 零基礎入門金融風控之貸款違約
目的:
-
1.EDA價值主要在于熟悉了解整個數據集的基本情況(缺失值,異常值),對數據集進行驗證是否可以進行接下來的機器學習或者深度學習建模.
-
2.了解變量間的相互關系、變量與預測值之間的存在關系。
-
3.為特征工程做準備
項目地址:https://github.com/datawhalechina/team-learning-data-mining/tree/master/FinancialRiskControl
比賽地址:https://tianchi.aliyun.com/competition/entrance/531830/introduction
2.1 學習目標
- 學習如何對數據集整體概況進行分析,包括數據集的基本情況(缺失值,異常值)
- 學習了解變量間的相互關系、變量與預測值之間的存在關系
- 完成相應學習打卡任務
2.2 內容介紹
- 數據總體了解:
- 讀取數據集并了解數據集大小,原始特征維度;
- 通過info熟悉數據類型;
- 粗略查看數據集中各特征基本統計量;
- 缺失值和唯一值:
- 查看數據缺失值情況
- 查看唯一值特征情況
- 深入數據-查看數據類型
- 類別型數據
- 數值型數據
- 離散數值型數據
- 連續數值型數據
- 數據間相關關系
- 特征和特征之間關系
- 特征和目標變量之間關系
- 用pandas_profiling生成數據報告
2.3 代碼示例
2.3.1 導入數據分析及可視化過程需要的庫
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import datetime import warnings warnings.filterwarnings('ignore') /Users/exudingtao/opt/anaconda3/lib/python3.7/site-packages/statsmodels/tools/_testing.py:19: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.import pandas.util.testing as tm以上庫都是pip install 安裝就好,如果本機有python2,python3兩個python環境傻傻分不清哪個的話,可以pip3 install 。或者直接在notebook中’!pip3 install ****'安裝。
說明:
本次數據分析探索,尤其可視化部分均選取某些特定變量進行了舉例,所以它只是一個方法的展示而不是整個賽題數據分析的解決方案。
2.3.2 讀取文件
data_train = pd.read_csv('./train.csv') data_test_a = pd.read_csv('./testA.csv')2.3.2.1讀取文件的拓展知識
- pandas讀取數據時相對路徑載入報錯時,嘗試使用os.getcwd()查看當前工作目錄。
- TSV與CSV的區別:
- 從名稱上即可知道,TSV是用制表符(Tab,’\t’)作為字段值的分隔符;CSV是用半角逗號(’,’)作為字段值的分隔符;
- Python對TSV文件的支持:
Python的csv模塊準確的講應該叫做dsv模塊,因為它實際上是支持范式的分隔符分隔值文件(DSV,delimiter-separated values)的。
delimiter參數值默認為半角逗號,即默認將被處理文件視為CSV。當delimiter=’\t’時,被處理文件就是TSV。
- 讀取文件的部分(適用于文件特別大的場景)
- 通過nrows參數,來設置讀取文件的前多少行,nrows是一個大于等于0的整數。
- 分塊讀取
2.3.3總體了解
查看數據集的樣本個數和原始特征維度
data_test_a.shape (200000, 48) data_train.shape (800000, 47) data_train.columns Index(['id', 'loanAmnt', 'term', 'interestRate', 'installment', 'grade','subGrade', 'employmentTitle', 'employmentLength', 'homeOwnership','annualIncome', 'verificationStatus', 'issueDate', 'isDefault','purpose', 'postCode', 'regionCode', 'dti', 'delinquency_2years','ficoRangeLow', 'ficoRangeHigh', 'openAcc', 'pubRec','pubRecBankruptcies', 'revolBal', 'revolUtil', 'totalAcc','initialListStatus', 'applicationType', 'earliesCreditLine', 'title','policyCode', 'n0', 'n1', 'n2', 'n2.1', 'n4', 'n5', 'n6', 'n7', 'n8','n9', 'n10', 'n11', 'n12', 'n13', 'n14'],dtype='object')查看一下具體的列名,賽題理解部分已經給出具體的特征含義,這里方便閱讀再給一下:
- id 為貸款清單分配的唯一信用證標識
- loanAmnt 貸款金額
- term 貸款期限(year)
- interestRate 貸款利率
- installment 分期付款金額
- grade 貸款等級
- subGrade 貸款等級之子級
- employmentTitle 就業職稱
- employmentLength 就業年限(年)
- homeOwnership 借款人在登記時提供的房屋所有權狀況
- annualIncome 年收入
- verificationStatus 驗證狀態
- issueDate 貸款發放的月份
- purpose 借款人在貸款申請時的貸款用途類別
- postCode 借款人在貸款申請中提供的郵政編碼的前3位數字
- regionCode 地區編碼
- dti 債務收入比
- delinquency_2years 借款人過去2年信用檔案中逾期30天以上的違約事件數
- ficoRangeLow 借款人在貸款發放時的fico所屬的下限范圍
- ficoRangeHigh 借款人在貸款發放時的fico所屬的上限范圍
- openAcc 借款人信用檔案中未結信用額度的數量
- pubRec 貶損公共記錄的數量
- pubRecBankruptcies 公開記錄清除的數量
- revolBal 信貸周轉余額合計
- revolUtil 循環額度利用率,或借款人使用的相對于所有可用循環信貸的信貸金額
- totalAcc 借款人信用檔案中當前的信用額度總數
- initialListStatus 貸款的初始列表狀態
- applicationType 表明貸款是個人申請還是與兩個共同借款人的聯合申請
- earliesCreditLine 借款人最早報告的信用額度開立的月份
- title 借款人提供的貸款名稱
- policyCode 公開可用的策略_代碼=1新產品不公開可用的策略_代碼=2
- n系列匿名特征 匿名特征n0-n14,為一些貸款人行為計數特征的處理
通過info()來熟悉數據類型
data_train.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 800000 entries, 0 to 799999 Data columns (total 47 columns):# Column Non-Null Count Dtype --- ------ -------------- ----- 0 id 800000 non-null int64 1 loanAmnt 800000 non-null float642 term 800000 non-null int64 3 interestRate 800000 non-null float644 installment 800000 non-null float645 grade 800000 non-null object 6 subGrade 800000 non-null object 7 employmentTitle 799999 non-null float648 employmentLength 753201 non-null object 9 homeOwnership 800000 non-null int64 10 annualIncome 800000 non-null float6411 verificationStatus 800000 non-null int64 12 issueDate 800000 non-null object 13 isDefault 800000 non-null int64 14 purpose 800000 non-null int64 15 postCode 799999 non-null float6416 regionCode 800000 non-null int64 17 dti 799761 non-null float6418 delinquency_2years 800000 non-null float6419 ficoRangeLow 800000 non-null float6420 ficoRangeHigh 800000 non-null float6421 openAcc 800000 non-null float6422 pubRec 800000 non-null float6423 pubRecBankruptcies 799595 non-null float6424 revolBal 800000 non-null float6425 revolUtil 799469 non-null float6426 totalAcc 800000 non-null float6427 initialListStatus 800000 non-null int64 28 applicationType 800000 non-null int64 29 earliesCreditLine 800000 non-null object 30 title 799999 non-null float6431 policyCode 800000 non-null float6432 n0 759730 non-null float6433 n1 759730 non-null float6434 n2 759730 non-null float6435 n2.1 759730 non-null float6436 n4 766761 non-null float6437 n5 759730 non-null float6438 n6 759730 non-null float6439 n7 759730 non-null float6440 n8 759729 non-null float6441 n9 759730 non-null float6442 n10 766761 non-null float6443 n11 730248 non-null float6444 n12 759730 non-null float6445 n13 759730 non-null float6446 n14 759730 non-null float64 dtypes: float64(33), int64(9), object(5) memory usage: 286.9+ MB總體粗略的查看數據集各個特征的一些基本統計量
data_train.describe()| 800000.000000 | 800000.000000 | 800000.000000 | 800000.000000 | 800000.000000 | 799999.000000 | 800000.000000 | 8.000000e+05 | 800000.000000 | 800000.000000 | ... | 759730.000000 | 759730.000000 | 759730.000000 | 759729.000000 | 759730.000000 | 766761.000000 | 730248.000000 | 759730.000000 | 759730.000000 | 759730.000000 |
| 399999.500000 | 14416.818875 | 3.482745 | 13.238391 | 437.947723 | 72005.351714 | 0.614213 | 7.613391e+04 | 1.009683 | 0.199513 | ... | 8.107937 | 8.575994 | 8.282953 | 14.622488 | 5.592345 | 11.643896 | 0.000815 | 0.003384 | 0.089366 | 2.178606 |
| 230940.252015 | 8716.086178 | 0.855832 | 4.765757 | 261.460393 | 106585.640204 | 0.675749 | 6.894751e+04 | 0.782716 | 0.399634 | ... | 4.799210 | 7.400536 | 4.561689 | 8.124610 | 3.216184 | 5.484104 | 0.030075 | 0.062041 | 0.509069 | 1.844377 |
| 0.000000 | 500.000000 | 3.000000 | 5.310000 | 15.690000 | 0.000000 | 0.000000 | 0.000000e+00 | 0.000000 | 0.000000 | ... | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
| 199999.750000 | 8000.000000 | 3.000000 | 9.750000 | 248.450000 | 427.000000 | 0.000000 | 4.560000e+04 | 0.000000 | 0.000000 | ... | 5.000000 | 4.000000 | 5.000000 | 9.000000 | 3.000000 | 8.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 |
| 399999.500000 | 12000.000000 | 3.000000 | 12.740000 | 375.135000 | 7755.000000 | 1.000000 | 6.500000e+04 | 1.000000 | 0.000000 | ... | 7.000000 | 7.000000 | 7.000000 | 13.000000 | 5.000000 | 11.000000 | 0.000000 | 0.000000 | 0.000000 | 2.000000 |
| 599999.250000 | 20000.000000 | 3.000000 | 15.990000 | 580.710000 | 117663.500000 | 1.000000 | 9.000000e+04 | 2.000000 | 0.000000 | ... | 11.000000 | 11.000000 | 10.000000 | 19.000000 | 7.000000 | 14.000000 | 0.000000 | 0.000000 | 0.000000 | 3.000000 |
| 799999.000000 | 40000.000000 | 5.000000 | 30.990000 | 1715.420000 | 378351.000000 | 5.000000 | 1.099920e+07 | 2.000000 | 1.000000 | ... | 70.000000 | 132.000000 | 79.000000 | 128.000000 | 45.000000 | 82.000000 | 4.000000 | 4.000000 | 39.000000 | 30.000000 |
8 rows × 42 columns
data_train.head(3).append(data_train.tail(3))| 0 | 35000.0 | 5 | 19.52 | 917.97 | E | E2 | 320.0 | 2 years | 2 | ... | 9.0 | 8.0 | 4.0 | 12.0 | 2.0 | 7.0 | 0.0 | 0.0 | 0.0 | 2.0 |
| 1 | 18000.0 | 5 | 18.49 | 461.90 | D | D2 | 219843.0 | 5 years | 0 | ... | NaN | NaN | NaN | NaN | NaN | 13.0 | NaN | NaN | NaN | NaN |
| 2 | 12000.0 | 5 | 16.99 | 298.17 | D | D3 | 31698.0 | 8 years | 0 | ... | 0.0 | 21.0 | 4.0 | 5.0 | 3.0 | 11.0 | 0.0 | 0.0 | 0.0 | 4.0 |
| 799997 | 6000.0 | 3 | 13.33 | 203.12 | C | C3 | 2582.0 | 10+ years | 1 | ... | 4.0 | 26.0 | 4.0 | 10.0 | 4.0 | 5.0 | 0.0 | 0.0 | 1.0 | 4.0 |
| 799998 | 19200.0 | 3 | 6.92 | 592.14 | A | A4 | 151.0 | 10+ years | 0 | ... | 10.0 | 6.0 | 12.0 | 22.0 | 8.0 | 16.0 | 0.0 | 0.0 | 0.0 | 5.0 |
| 799999 | 9000.0 | 3 | 11.06 | 294.91 | B | B3 | 13.0 | 5 years | 0 | ... | 3.0 | 4.0 | 4.0 | 8.0 | 3.0 | 7.0 | 0.0 | 0.0 | 0.0 | 2.0 |
6 rows × 47 columns
2.3.4查看數據集中特征缺失值,唯一值等
查看缺失值
print(f'There are {data_train.isnull().any().sum()} columns in train dataset with missing values.') There are 22 columns in train dataset with missing values.上面得到訓練集有22列特征有缺失值,進一步查看缺失特征中缺失率大于50%的特征
have_null_fea_dict = (data_train.isnull().sum()/len(data_train)).to_dict() fea_null_moreThanHalf = {} for key,value in have_null_fea_dict.items():if value > 0.5:fea_null_moreThanHalf[key] = value fea_null_moreThanHalf {}具體的查看缺失特征及缺失率
# nan可視化 missing = data_train.isnull().sum()/len(data_train) missing = missing[missing > 0] missing.sort_values(inplace=True) missing.plot.bar() <matplotlib.axes._subplots.AxesSubplot at 0x1229ab890>- 縱向了解哪些列存在 “nan”, 并可以把nan的個數打印,主要的目的在于查看某一列nan存在的個數是否真的很大,如果nan存在的過多,說明這一列對label的影響幾乎不起作用了,可以考慮刪掉。如果缺失值很小一般可以選擇填充。
- 另外可以橫向比較,如果在數據集中,某些樣本數據的大部分列都是缺失的且樣本足夠的情況下可以考慮刪除。
Tips:
比賽大殺器lgb模型可以自動處理缺失值,Task4模型會具體學習模型了解模型哦!
查看訓練集測試集中特征屬性只有一值的特征
one_value_fea = [col for col in data_train.columns if data_train[col].nunique() <= 1] one_value_fea_test = [col for col in data_test_a.columns if data_test_a[col].nunique() <= 1] one_value_fea ['policyCode'] one_value_fea_test ['policyCode'] print(f'There are {len(one_value_fea)} columns in train dataset with one unique value.') print(f'There are {len(one_value_fea_test)} columns in test dataset with one unique value.') There are 1 columns in train dataset with one unique value. There are 1 columns in test dataset with one unique value.總結:
47列數據中有22列都缺少數據,這在現實世界中很正常。‘policyCode’具有一個唯一值(或全部缺失)。有很多連續變量和一些分類變量。
2.3.5 查看特征的數值類型有哪些,對象類型有哪些
- 特征一般都是由類別型特征和數值型特征組成,而數值型特征又分為連續型和離散型。
- 類別型特征有時具有非數值關系,有時也具有數值關系。比如‘grade’中的等級A,B,C等,是否只是單純的分類,還是A優于其他要結合業務判斷。
- 數值型特征本是可以直接入模的,但往往風控人員要對其做分箱,轉化為WOE編碼進而做標準評分卡等操作。從模型效果上來看,特征分箱主要是為了降低變量的復雜性,減少變量噪音對模型的影響,提高自變量和因變量的相關度。從而使模型更加穩定。
數值型變量分析,數值型肯定是包括連續型變量和離散型變量的,找出來
- 劃分數值型變量中的連續變量和離散型變量
- 數值類別型變量分析
- 數值連續型變量分析
- 查看某一個數值型變量的分布,查看變量是否符合正態分布,如果不符合正太分布的變量可以log化后再觀察下是否符合正態分布。
- 如果想統一處理一批數據變標準化 必須把這些之前已經正態化的數據提出
- 正態化的原因:一些情況下正態非正態可以讓模型更快的收斂,一些模型要求數據正態(eg. GMM、KNN),保證數據不要過偏態即可,過于偏態可能會影響模型預測結果。
- 非數值類別型變量分析
總結:
- 上面我們用value_counts()等函數看了特征屬性的分布,但是圖表是概括原始信息最便捷的方式。
- 數無形時少直覺。
- 同一份數據集,在不同的尺度刻畫上顯示出來的圖形反映的規律是不一樣的。python將數據轉化成圖表,但結論是否正確需要由你保證。
2.3.6 變量分布可視化
單一變量分布可視化
plt.figure(figsize=(8, 8)) sns.barplot(data_train["employmentLength"].value_counts(dropna=False)[:20],data_train["employmentLength"].value_counts(dropna=False).keys()[:20]) plt.show()根絕y值不同可視化x某個特征的分布
- 首先查看類別型變量在不同y值上的分布
- 其次查看連續型變量在不同y值上的分布
2.3.6 時間格式數據處理及查看
#轉化成時間格式 issueDateDT特征表示數據日期離數據集中日期最早的日期(2007-06-01)的天數 data_train['issueDate'] = pd.to_datetime(data_train['issueDate'],format='%Y-%m-%d') startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d') data_train['issueDateDT'] = data_train['issueDate'].apply(lambda x: x-startdate).dt.days #轉化成時間格式 data_test_a['issueDate'] = pd.to_datetime(data_train['issueDate'],format='%Y-%m-%d') startdate = datetime.datetime.strptime('2007-06-01', '%Y-%m-%d') data_test_a['issueDateDT'] = data_test_a['issueDate'].apply(lambda x: x-startdate).dt.days plt.hist(data_train['issueDateDT'], label='train'); plt.hist(data_test_a['issueDateDT'], label='test'); plt.legend(); plt.title('Distribution of issueDateDT dates'); #train 和 test issueDateDT 日期有重疊 所以使用基于時間的分割進行驗證是不明智的2.3.7 掌握透視圖可以讓我們更好的了解數據
#透視圖 索引可以有多個,“columns(列)”是可選的,聚合函數aggfunc最后是被應用到了變量“values”中你所列舉的項目上。 pivot = pd.pivot_table(data_train, index=['grade'], columns=['issueDateDT'], values=['loanAmnt'], aggfunc=np.sum) pivot| NaN | 53650.0 | 42000.0 | 19500.0 | 34425.0 | 63950.0 | 43500.0 | 168825.0 | 85600.0 | 101825.0 | ... | 13093850.0 | 11757325.0 | 11945975.0 | 9144000.0 | 7977650.0 | 6888900.0 | 5109800.0 | 3919275.0 | 2694025.0 | 2245625.0 |
| NaN | 13000.0 | 24000.0 | 32125.0 | 7025.0 | 95750.0 | 164300.0 | 303175.0 | 434425.0 | 538450.0 | ... | 16863100.0 | 17275175.0 | 16217500.0 | 11431350.0 | 8967750.0 | 7572725.0 | 4884600.0 | 4329400.0 | 3922575.0 | 3257100.0 |
| NaN | 68750.0 | 8175.0 | 10000.0 | 61800.0 | 52550.0 | 175375.0 | 151100.0 | 243725.0 | 393150.0 | ... | 17502375.0 | 17471500.0 | 16111225.0 | 11973675.0 | 10184450.0 | 7765000.0 | 5354450.0 | 4552600.0 | 2870050.0 | 2246250.0 |
| NaN | NaN | 5500.0 | 2850.0 | 28625.0 | NaN | 167975.0 | 171325.0 | 192900.0 | 269325.0 | ... | 11403075.0 | 10964150.0 | 10747675.0 | 7082050.0 | 7189625.0 | 5195700.0 | 3455175.0 | 3038500.0 | 2452375.0 | 1771750.0 |
| 7500.0 | NaN | 10000.0 | NaN | 17975.0 | 1500.0 | 94375.0 | 116450.0 | 42000.0 | 139775.0 | ... | 3983050.0 | 3410125.0 | 3107150.0 | 2341825.0 | 2225675.0 | 1643675.0 | 1091025.0 | 1131625.0 | 883950.0 | 802425.0 |
| NaN | NaN | 31250.0 | 2125.0 | NaN | NaN | NaN | 49000.0 | 27000.0 | 43000.0 | ... | 1074175.0 | 868925.0 | 761675.0 | 685325.0 | 665750.0 | 685200.0 | 316700.0 | 315075.0 | 72300.0 | NaN |
| NaN | NaN | NaN | NaN | NaN | NaN | NaN | 24625.0 | NaN | NaN | ... | 56100.0 | 243275.0 | 224825.0 | 64050.0 | 198575.0 | 245825.0 | 53125.0 | 23750.0 | 25100.0 | 1000.0 |
7 rows × 139 columns
2.3.8 用pandas_profiling生成數據報告
import pandas_profiling pfr = pandas_profiling.ProfileReport(data_train) pfr.to_file("./example.html")2.4 總結
數據探索性分析是我們初步了解數據,熟悉數據為特征工程做準備的階段,甚至很多時候EDA階段提取出來的特征可以直接當作規則來用。可見EDA的重要性,這個階段的主要工作還是借助于各個簡單的統計量來對數據整體的了解,分析各個類型變量相互之間的關系,以及用合適的圖形可視化出來直觀觀察。
總結
以上是生活随笔為你收集整理的【算法竞赛学习】金融风控之贷款违约预测-数据分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 可覆盖1万平商场!小米对讲机2S图赏
- 下一篇: ChatGPT 化身硅谷资本家,学大厂