主頁 >  其他 > 基于決策樹模型的金融保險用戶分類綜合專案【資料可視化&相關性分析&填充缺失值&轉碼&建模&商業應用】

基于決策樹模型的金融保險用戶分類綜合專案【資料可視化&相關性分析&填充缺失值&轉碼&建模&商業應用】

2021-09-17 08:07:29 其他

超詳細的一篇資料分析實戰案例,模擬真實業務,建議收藏慢慢閱讀!

目錄

  • 必看前言
  • 1 行業背景
    • 1.1 業務環境
    • 1.2 發展現狀
    • 1.3 發展趨勢
    • 1.4 衡量指標
  • 2 資料介紹
    • 2.1 基本資訊
    • 2.2 家庭資訊
    • 2.3 家庭成員
    • 2.4 疾病史
    • 2.5 金融資訊
    • 2.6 個人習慣
    • 2.7 家庭狀況
    • 2.8 居住城市
  • 3 案例分析
    • 3.1 分析流程
      • 3.1.1 匯入資料,觀察資料
      • 3.1.2 探索資料&資料可視化分析
        • 3.1.2.1 處理列標簽名例外
        • 3.1.2.2 創建自定義翻譯函式
        • 3.1.2.3 探索用戶基本資訊
        • 3.1.2.4 探索家庭成員欄位資訊
        • 3.1.2.5 探索疾病相關欄位
        • 3.1.2.6 探索投資相關欄位
        • 3.1.2.7 探索生活習慣
        • 3.1.2.8 探索家庭收入
        • 3.1.2.9 探索所處地區情況
      • 3.1.3 資料清洗
        • 3.1.3.1 洗掉特征
        • 3.1.3.2 洗掉重復值
        • 3.1.3.3 劃分訓練集與測驗集
        • 3.1.3.4 填充缺失值
      • 3.1.4 轉碼
        • 3.1.4.1 0-1轉碼
        • 3.1.4.2 啞變數轉碼
        • 3.1.4.3 對測驗集進行轉碼(總結)
      • 3.1.5 資料建模與評估
        • 3.1.5.1 初步建模
        • 3.1.5.2 網格搜索找最優引數
        • 3.1.5.3 模型評估
        • 3.1.5.4 輸出規則
      • 3.1.6 輸出結果的商業應用
        • 3.1.6.1 第一類
        • 3.1.6.2 第二類
        • 3.1.6.3 了解客戶需求
        • 3.1.6.4 開發新的產品
  • 結束語

必看前言

本次文章將會介紹一篇基于決策樹模型的金融保險用戶分類綜合專案,我會從行業背景講起,將整個專案包括代碼全po上來,大家看目錄就知道有多么詳細啦,

1 行業背景

1.1 業務環境

  • 宏觀
    中國是世界第二大保險市場,但在保險密度上與世界平均水平仍有明顯差距,
  • 業界
    保險行業2018年保費規模為3.8萬億,同比增長不足4%,過去"短平快"的發展模式已經不能適應新時代的行業發展需求,行業及用戶長期存在難以解決的痛點,限制了行業發展,
  • 社會
    互聯網經濟的發展,為保險行業帶來了增量市場,同時隨著網民規模的擴大,用戶的行為習慣已發生轉變,這些都需要互聯網的方式進行觸達,保險科技∶當前沿科技不斷應用于保險行業,互聯網保險的概念將會與保險科技概念高度融合,

在這里插入圖片描述
中國保險市場持續高速增長,根據保監會資料,2011~2018年,全國保費收入從1.4萬億增長至3.8萬億,年復合增長率17.2%,2014年,中國保費收入突破2萬億,成為全球僅次于美國、日本的第三大新興保險市場市場;2016年,中國整體保費入突破3萬億,超過日本,成為全球第二大保險市場;2019年,中國保費收入突破4萬億,

1.2 發展現狀

  • 概覽
    受保險行業結構轉型時期影響,互聯網保險整體發展受阻,2018年行業保費收入為1889億元,較17年持平,不同險種發展呈現分化格局,其中健康險增長迅猛,2018年同比增長108%,主要由短期醫療險驅動,
  • 格局
    供給端專業互聯網保險公司增長迅速,但過高的固定成本及渠道費用使得其盈利問題凸顯,加上發展現狀強,自營渠道建設及科技輸出是未來的破局方法,渠道端形成第三方平臺為主,官網為輔的格局,第三方平臺逐漸發展出B2C、B2A、B2B2C等多種創新業務模式,
  • 模式
    互聯網保險不僅僅局限于渠道創新,其核心優勢同樣體現在產品設計的創新和服務體驗的提升,

1.3 發展趨勢

  • 競合格局
    隨著入局企業增多,流量爭奪更加激烈,最終保險公司與第三方平臺深度合作將成為常態,
  • 保險科技
    當前沿科技不斷應用于保險行業,互聯網保險的概念將會與保險科技概念高度融合,

1.4 衡量指標

在這里插入圖片描述

2 資料介紹

  • 資料來源
    美國某保險公司,該公司的一款醫療產品準備上市,
  • 商品介紹
    這是一款針對65歲人群推出的醫療附加險,銷售渠道是直郵,
  • 商業目的
    為該產品做用戶畫像,找到最具購買傾向的人群進行營銷,

本次案例資料中共有76個欄位,欄位繁多,在處理資料時,需要先將資料按照類別進行劃分,方便理解查看,

2.1 基本資訊

變數名稱變數含義備注
KBM_INDY_ID用戶ID無意義特征
resp_flag用戶是否購買保險我們的目標變數
age用戶年齡本產品為針對65歲以上的人群保險
GEDN性別
c210mys學歷0-unknown; 1-初中; 2-高中不到; 3-高中畢業; 4-大學未畢業; 5-大專; 6-本科; 7-研究生; 8-專業院校畢業; 9-博士
POC19是否有小孩
CA[XX]小孩年齡

2.2 家庭資訊

變數名稱變數含義備注
NOC19家庭小孩個數
NAH19家庭成年人個數
NPH19家庭成員人數
POEP家庭是否為有老人

2.3 家庭成員

變數名稱變數含義備注
U18是否有家庭成員小于18歲
N1819是否有家庭成員在18-19歲之間
N2029是否有家庭成員在20-29歲之間
N3039是否有家庭成員在30-39歲之間
N4049是否有家庭成員在40-49歲之間
N5059是否有家庭成員在50-59歲之間
N6064是否有家庭成員在60-64歲之間
N65P是否有家庭成員在65歲以上

2.4 疾病史

變數名稱變數含義備注
AART是否有關節炎
ADBT是否有糖尿病
ADEP是否有抑郁癥
AHBP是否有高血壓
AHCH膽固醇含量是否過高
ARES是否有呼吸疾病

2.5 金融資訊

變數名稱變數含義備注
BANK是否有過破產記錄
FINI是否有過保險服務
INLI是否投資過壽險
INMEDI是否購買過醫療險
INVE是否有投資

2.6 個人習慣

變數名稱變數含義備注
IOLP是否網上購買過產品
MOBPLUS是否通過快遞買過東西M-通過多種快遞渠道購買;P-或許通過多種快遞渠道購買;S-單一快遞渠道購買;U-不知道;
ONLA是否上網
SGFA是否喜歡美術
SGLL是否經常有奢侈消費
SGDE是否經常戶外活動
SGSE是否喜歡運動

2.7 家庭狀況

變數名稱變數含義備注
LIVEWELL幸福指數值越大,說明越幸福
HOMSTAT是否有房子Y:有房子;P:可能有房子;R:租房;TU:不確定
HINSUB是否有醫保補貼A-C,補貼依次增加
c210cip收入所處排名值越大,說明收入越高
c210ebi普查家庭有效購買收入值越大,說明有效購買收入越高
c210hmi家庭收入值越大,說明家庭收入越高
c210hva家庭房屋價值值越大,說明房屋價值越高
c210…家庭經濟類資料值越大,說明經濟地位越高

2.8 居住城市

變數名稱變數含義備注
STATE_NAME是否網上購買過產品
c210apvt貧窮以上人的比例值越大,說明比例越高
c210b200所處地區有多少居住小區在2000年后建立值越大,說明比例越高
c210blu所處地區藍領所占百分比值越大,說明比例越高
c210bpvt貧窮以下人的比例值越大,說明比例越高
c210mob所處地區mobile home的比例值越大,說明比例越高
c210pdv離婚或者分局人群所占比例值越大,說明比例越高
居住地統計資料值越大,說明比例越高

3 案例分析

我們可以大概判別哪些特征很可能和用戶是否購買保隙訓有相關關系,

也可以結合我們的業務經驗,以及資料可視化,特征工程方法,先行探索一下,這些特征中哪些特征更重要一些,

可以在建模之后,再回顧我們這里認為比較重要或不重要的特征,看一下判斷是否準確,

3.1 分析流程

  1. 匯入資料,觀察資料
  2. 探索資料 & 資料可視化分析(探索缺失值填充方案、轉碼方案、一些特殊欄位的處理方案等)
  3. 空值填充
  4. 變數編碼
  5. 資料建模
  6. 輸出規則(決策樹圖)
#全部行都能輸出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# 解決坐標軸刻度負號亂碼
plt.rcParams['axes.unicode_minus'] = False

# 解決中文亂碼問題
plt.rcParams['font.sans-serif'] = ['Simhei']

3.1.1 匯入資料,觀察資料

data_00 = pd.read_csv('data/ma_resp_data_temp.csv')
feature_dict = pd.read_excel('保險案例資料字典.xlsx')
data_01 = data_00.copy()

3.1.2 探索資料&資料可視化分析

注意:在我們進行探索資料時,可以結合一下EXCEL,用EXCEL來記錄資料后續需要進行的對應操作(可以分成洗掉、轉換、填充三種情況),這樣也方便我們后續進行資料清洗,

data_01.head()

在這里插入圖片描述

feature_dict

在這里插入圖片描述

3.1.2.1 處理列標簽名例外

表中的欄位與資料字典不匹配,

判斷data_01中的列標簽名是否都出現在資料字典的變數名中,

data_01.columns

在這里插入圖片描述

feature_dict.變數名

在這里插入圖片描述

#求補集
np.setxor1d(data_01.columns,feature_dict.變數名) 

在這里插入圖片描述

'''
#資料表列標簽
NY8Y9', 'N2N29', 'N3N39', 'N4N49', 'N5N59', 'N6N64'

#資料字典
'N1819', 'N2029','N3039','N4049', 'N5059','N6064'

meda # 這個莫名其妙,刪掉
'''
# 刪掉
data_01['meda'].nunique()

75

替換例外標簽

a = ['NY8Y9', 'N2N29', 'N3N39', 'N4N49', 'N5N59', 'N6N64']
b = ['N1819', 'N2029','N3039','N4049', 'N5059','N6064']
# 要替換的列標簽,做成映射字典
dic = dict(zip(a,b))
dic
#自定義要轉化的向量化函式
def tran(x):
    if x in dic:
        return dic[x]
    else:
        return x
tran = np.vectorize(tran) #向量化

#使用向量化函式替換例外表頭
data_01.columns = tran(data_01.columns)

在這里插入圖片描述

3.1.2.2 創建自定義翻譯函式

提高探索資料效率,創建自定義翻譯函式,通過映射字典的方式,替換DataFrame列標簽名為中文:

dic = {k:v for k,v in feature_dict[['變數名','變數說明']].values.reshape(-1,2)}

def chinese(x):
    y = x.copy()
    #將輸入進來的欄位名通過字典映射的方式去對應
    y.columns = pd.Series(y.columns).map(dic)
    return y
chinese(data_01).head()

在這里插入圖片描述

3.1.2.3 探索用戶基本資訊

feature_dict.變數名[:5]

在這里插入圖片描述

feature_dict.變數名[:5].tolist() #得到串列

在這里插入圖片描述

data_01[feature_dict.變數名[:5].tolist()].head()

在這里插入圖片描述

#將0_4列取出來并進行翻譯
data0_4 = chinese(data_01[feature_dict.變數名[:5].tolist()])
data0_4.head()

在這里插入圖片描述
下面來看一下資料的基本資訊,

data0_4.info()

在這里插入圖片描述
再看一下缺失值

data0_4.isnull().sum()

在這里插入圖片描述
發現是有缺失的(后續要處理),

同時,我們不難發現上面這些方法都是常用到的,可以考慮封裝成函式,方便后續使用,

自定義探索特征頻率函式

輸入一個DataFrame,輸出每個特征的頻數分布:

def fre(x):
    for i in x.columns:
        print("欄位名:",i)
        print("----------")
        print("欄位資料型別:",x[i].dtype)
        print("----------------------------")
        print(x[i].value_counts()) #頻數
        print("----------------------------")
        print("缺失值的個數:",x[i].isnull().sum())
        print("------------------------------------------------\n\n")

fre(data0_4)

輸出結果如下:

欄位名: Individual ID
----------
欄位資料型別: int64
----------------------------
142936063    1
68797618     1
193209817    1
172309160    1
171816124    1
            ..
172641155    1
76214763     1
228943803    1
185032198    1
1966080      1
Name: Individual ID, Length: 43666, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否response
----------
欄位資料型別: int64
----------------------------
0    26177
1    17489
Name: 是否response, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 年齡
----------
欄位資料型別: float64
----------------------------
66.0     3967
67.0     3670
65.0     3475
69.0     3449
68.0     3423
70.0     2948
71.0     2943
72.0     2909
74.0     2817
73.0     2814
75.0     2448
76.0     2220
78.0     2038
77.0     2012
79.0     1823
80.0      691
91.0        2
86.0        2
88.0        2
96.0        1
99.0        1
82.0        1
95.0        1
90.0        1
98.0        1
87.0        1
94.0        1
101.0       1
Name: 年齡, dtype: int64
----------------------------
缺失值的個數: 4
------------------------------------------------


欄位名: 性別
----------
欄位資料型別: object
----------------------------
F    25405
M    18261
Name: 性別, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 學歷
----------
欄位資料型別: int64
----------------------------
4    18597
3    12437
6     7493
5     4474
2      462
7      130
0       60
1        9
8        4
Name: 學歷, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------
  • Individual ID是我們要刪的(后面也有一個ID);
  • 是否response則是我們的標簽;
  • 年齡則是有些缺失值(年齡有高有低,最高都101歲,可以考慮用中位數填充);
  • 性別則是需要進行0-1編碼;
  • 學歷需要轉成啞變數(即one-hot編碼),

來看一下購買情況,

import seaborn as sns

#中文編碼
sns.set_style("darkgrid",{"font.sans-serif":['simhei','Droid Sans Fallback']})
#sns.set()

plt.figure(1,figsize=(6,2))
sns.countplot(y='是否response',data=data0_4)
plt.show()

在這里插入圖片描述
差別不是很大,后續使用class_weight引數與否也不重要,

#根據年齡   概率密度圖
sns.kdeplot(data0_4.年齡[data0_4.是否response==1],label='購買')
sns.kdeplot(data0_4.年齡[data0_4.是否response==0],label='不購買')
sns.kdeplot(data0_4.年齡.dropna(),label='所有人')

plt.xlim([60,90])
plt.xlabel('Age')
plt.ylabel('Density')

在這里插入圖片描述

3.1.2.4 探索家庭成員欄位資訊

#將5_22列取出來并進行翻譯
data5_22 = chinese(data_01[feature_dict.變數名[5:23].tolist()])
data5_22.head()

在這里插入圖片描述
呼叫一下剛自定好的函式,

fre(data5_22)

輸出結果為:

欄位名: 是否有小孩
----------
欄位資料型別: object
----------------------------
U    24500
Y    10225
P     8941
Name: 是否有小孩, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 小孩是否在0-2歲之間
----------
欄位資料型別: int64
----------------------------
0    40677
4     2856
1       57
2       48
3       16
6        9
5        3
Name: 小孩是否在0-2歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 小孩是否在3-5歲之間
----------
欄位資料型別: int64
----------------------------
0    41087
4     2068
1      204
2      202
3       45
5       30
6       29
7        1
Name: 小孩是否在3-5歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 小孩是否在6-10歲之間
----------
欄位資料型別: int64
----------------------------
0    38969
4     2960
1      553
2      528
6      240
5      209
3      176
7       31
Name: 小孩是否在6-10歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 小孩是否在11-15歲之間
----------
欄位資料型別: int64
----------------------------
0    39430
4     2281
1      757
2      651
3      211
5      176
6      140
7       20
Name: 小孩是否在11-15歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 小孩是否在16-18歲之間
----------
欄位資料型別: int64
----------------------------
0    40243
4     1590
1      826
2      718
3      164
5       70
6       54
7        1
Name: 小孩是否在16-18歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 家庭小孩個數
----------
欄位資料型別: int64
----------------------------
0    33441
1     5089
2     2365
3     1298
4     1008
5      290
6      116
7       30
8       26
9        3
Name: 家庭小孩個數, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 家庭成年人個數
----------
欄位資料型別: int64
----------------------------
1    15792
2    13414
3     7633
4     3942
5     1292
0     1105
6      349
7      101
8       29
9        9
Name: 家庭成年人個數, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 家庭成員人數量
----------
欄位資料型別: int64
----------------------------
1     14970
2     11148
3      6120
4      4123
5      2499
6      1547
0      1105
7       994
8       569
9       316
10      152
11       79
12       25
13       12
15        3
14        3
16        1
Name: 家庭成員人數量, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員小于18歲
----------
欄位資料型別: object
----------------------------
N    43665
Y        1
Name: 是否有家庭成員小于18歲, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員在18-19歲之間
----------
欄位資料型別: object
----------------------------
N    43579
Y       78
Name: 是否有家庭成員在18-19歲之間, dtype: int64
----------------------------
缺失值的個數: 9
------------------------------------------------


欄位名: 是否有家庭成員在20-29歲之間
----------
欄位資料型別: object
----------------------------
N    41318
Y     2348
Name: 是否有家庭成員在20-29歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員在30-39歲之間
----------
欄位資料型別: object
----------------------------
N    36624
Y     7042
Name: 是否有家庭成員在30-39歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員在40-49歲之間
----------
欄位資料型別: object
----------------------------
N    34740
Y     8926
Name: 是否有家庭成員在40-49歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員在50-59歲之間
----------
欄位資料型別: object
----------------------------
N    38345
Y     5321
Name: 是否有家庭成員在50-59歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員在60-64歲之間
----------
欄位資料型別: object
----------------------------
N    39544
Y     4121
0        1
Name: 是否有家庭成員在60-64歲之間, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有家庭成員在65歲以上
----------
欄位資料型別: object
----------------------------
Y    42461
N     1205
Name: 是否有家庭成員在65歲以上, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 家里是否有老人
----------
欄位資料型別: object
----------------------------
N    33522
Y    10136
Name: 家里是否有老人, dtype: int64
----------------------------
缺失值的個數: 8
------------------------------------------------
  • 是否有小孩這個欄位有三種值:U代表不知道,Y代表有,P表示可能有(美國老人和子女間的聯系比較少,不知道自己有沒有孫子孫女),后續轉成啞變數;
  • 小孩是否在0~2歲之間:我們發現有4個0~2歲的小孩的數量有2856,如果是子女的話很不科學,所以我們猜測是孫子孫女(所以上面的P才解釋得通);
  • 是否有家庭成員是小于18歲的:發現只有1個資料是有小于18歲的成員的,與上述資料完全不符,說明這個資料是有問題的,后續需要刪掉
  • 是有有家庭成員在18~19歲之間:存在缺失值,考慮用眾數填充;
  • 是否有家庭成員在60~64歲之間:發現有個資料是0,懷疑可能原本是N弄成了0,后續可以將0替換成N;
  • 家里是否有老人:我們統計的物件本來就是老人,但是資料卻很多沒有老人,推測可能存在物件覺得自己不算在其中的情況,我們可以考慮將這個欄位刪掉;
  • 其他欄位可以將N和P轉成0和1;

3.1.2.5 探索疾病相關欄位

老套路:

#將23_35列取出來并進行翻譯
data23_35 = chinese(data_01[feature_dict.變數名[23:35].tolist()])
data23_35.head()

在這里插入圖片描述

fre(data23_35)
欄位名: 是否有關節炎
----------
欄位資料型別: object
----------------------------
N    38369
Y     5297
Name: 是否有關節炎, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有糖尿病
----------
欄位資料型別: object
----------------------------
N    40554
Y     3112
Name: 是否有糖尿病, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有抑郁癥
----------
欄位資料型別: object
----------------------------
N    41674
Y     1992
Name: 是否有抑郁癥, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有高血壓
----------
欄位資料型別: object
----------------------------
N    38102
Y     5564
Name: 是否有高血壓, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 膽固醇含量是否過高
----------
欄位資料型別: object
----------------------------
N    37395
Y     6271
Name: 膽固醇含量是否過高, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有呼吸疾病
----------
欄位資料型別: object
----------------------------
N    40900
Y     2766
Name: 是否有呼吸疾病, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有心臟病
----------
欄位資料型別: object
----------------------------
N    41733
Y     1933
Name: 是否有心臟病, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有過敏性鼻炎
----------
欄位資料型別: object
----------------------------
N    36824
Y     6832
Name: 是否有過敏性鼻炎, dtype: int64
----------------------------
缺失值的個數: 10
------------------------------------------------


欄位名: 是否有消化不良
----------
欄位資料型別: object
----------------------------
N    37381
Y     6285
Name: 是否有消化不良, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否耳聾
----------
欄位資料型別: object
----------------------------
N    42082
Y     1584
Name: 是否耳聾, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有皮膚病
----------
欄位資料型別: object
----------------------------
N    41161
Y     2497
Name: 是否有皮膚病, dtype: int64
----------------------------
缺失值的個數: 8
------------------------------------------------


欄位名: 是否視力不好
----------
欄位資料型別: object
----------------------------
N    38399
Y     5267
Name: 是否視力不好, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------
  • 是否有過敏性鼻炎:有10個缺失值,考慮用眾數填充;
  • 是否有皮膚病:有8個缺失值,考慮用眾數填充;
  • N和P轉成0和1,

從常理性來講,疾病之間很可能是存在相關性的,所以我們可以看看這些欄位之間的相關性(畫熱力圖),找到高度相關的欄位并洗掉,

那我們得先將欄位資料 轉換成0-1編碼:

#0 1 轉碼
def zero_one(x):
    for i in x.columns:
        if x[i].dtype == 'object':
            dic = dict(zip(list(x[i].value_counts().index),range(x[i].nunique())))
            x[i] = x[i].map(dic)
    return x

zero_one(data23_35).corr()

在這里插入圖片描述
單看表可能比較頭疼,下面我們畫張熱力圖看看:

import matplotlib.pyplot as plt
import seaborn as sns

sns.heatmap(zero_one(data23_35).corr(),cmap='Blues')

在這里插入圖片描述
越藍相關性越高,肉眼可以看出來相關性了,不過還是寫個函式直接輸出相關性高的欄位更好,這里我們輸出相關性高于0.65的欄位(可以刪,但不然刪太多,對決策樹的創建也不好),

def higt_cor(x,y=0.65):
    data_cor = (x.corr()>y)
    a=[]
    
    for i in data_cor.columns:
        if data_cor[i].sum()>=2:  # 有兩個或兩個以上的TRUE
            a.append(i)

    return a  #這些是我們要考慮洗掉的

higt_cor(data23_35) #是否有關節炎  膽固醇含量是否過高  是否有過敏性鼻炎

[‘是否有關節炎’, ‘是否有高血壓’, ‘膽固醇含量是否過高’, ‘是否有過敏性鼻炎’, ‘是否有消化不良’]

我們可以再結合一下圖,考慮洗掉是否有關節炎 膽固醇含量是否過高 是否有過敏性鼻炎這三個欄位,

3.1.2.6 探索投資相關欄位

老套路:

#將35_41列取出來并進行翻譯
data35_41 = chinese(data_01[feature_dict.變數名[35:41].tolist()])
data35_41.head()

在這里插入圖片描述

  • 都是要改成0-1編碼,
fre(data35_41)
欄位名: 是否有過破產記錄
----------
欄位資料型別: object
----------------------------
N    40599
Y     3067
Name: 是否有過破產記錄, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否大學畢業
----------
欄位資料型別: object
----------------------------
N    39236
Y     4422
Name: 是否大學畢業, dtype: int64
----------------------------
缺失值的個數: 8
------------------------------------------------


欄位名: 是否用過保險服務
----------
欄位資料型別: object
----------------------------
N    42793
Y      873
Name: 是否用過保險服務, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否投資過壽險
----------
欄位資料型別: object
----------------------------
N    35871
Y     7795
Name: 是否投資過壽險, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否購買過醫療險
----------
欄位資料型別: object
----------------------------
N    40016
Y     3650
Name: 是否購買過醫療險, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否有投資
----------
欄位資料型別: object
----------------------------
N    33896
Y     9770
Name: 是否有投資, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------

  • 是否大學畢業:存在缺失值,不過這個資料明顯和之前的學歷資訊重復了,可以刪掉,

接下來還是畫圖看一下屬性間的相關性:

sns.heatmap(zero_one(data35_41).corr(),cmap='Blues')

在這里插入圖片描述
可以看到后下角顏色明顯很深,

是否有過投資和是否投資過壽險明顯相關,當然我們也可以再呼叫一下函式查看結果:

higt_cor(data35_41)

[‘是否投資過壽險’, ‘是否有投資’]

結果確實是這樣,那我們這個時候要考慮洗掉其中哪一個?

我們結合一下我們的目的——推薦醫療附加險,是否投資過壽險感覺更貼合我們的目的,所以考慮刪掉是否有投資這個欄位,

3.1.2.7 探索生活習慣

老套路:

#將41_51列取出來并進行翻譯
data41_51 = chinese(data_01[feature_dict.變數名[41:51].tolist()])
data41_51.head()

在這里插入圖片描述
還是都要改成0-1編碼,

我們接著在呼叫一下函式:

fre(data41_51)
欄位名: 是否網上購買過產品
----------
欄位資料型別: object
----------------------------
N    36197
Y     7469
Name: 是否網上購買過產品, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否通過快遞買過東西
----------
欄位資料型別: object
----------------------------
M    27450
S     9947
U     3912
P     2350
Name: 是否通過快遞買過東西, dtype: int64
----------------------------
缺失值的個數: 7
------------------------------------------------


欄位名: 所處的縣的大小
----------
欄位資料型別: object
----------------------------
A    26539
B    12687
C     3823
D      607
Name: 所處的縣的大小, dtype: int64
----------------------------
缺失值的個數: 10
------------------------------------------------


欄位名: 是否上網
----------
欄位資料型別: object
----------------------------
Y    28473
N    15193
Name: 是否上網, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否喜歡美術
----------
欄位資料型別: object
----------------------------
N    37029
Y     6637
Name: 是否喜歡美術, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否經常有奢侈消費
----------
欄位資料型別: object
----------------------------
N    33801
Y     9865
Name: 是否經常有奢侈消費, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否經常戶外活動
----------
欄位資料型別: object
----------------------------
N    35728
Y     7938
Name: 是否經常戶外活動, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否喜歡運動
----------
欄位資料型別: object
----------------------------
N    31867
Y    11799
Name: 是否喜歡運動, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 是否熱愛科技
----------
欄位資料型別: object
----------------------------
N    31370
Y    12296
Name: 是否熱愛科技, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 幸福指數
----------
欄位資料型別: float64
----------------------------
4.0    16093
3.0    11975
1.0     8837
2.0     6395
6.0      361
Name: 幸福指數, dtype: int64
----------------------------
缺失值的個數: 5
------------------------------------------------
  • 是否通過快遞買過東西:轉成啞變數,同時用眾數填補缺失值;
  • 所處的縣的大小:轉成啞變數,同時用眾數填補缺失值;
  • 其他欄位則改成0-1編碼,

我們也可以來看下縣的大小和購買結果的關系:

sns.countplot(x='N2NCY',hue='resp_flag',data=data_01)
plt.xlabel('縣的大小')
plt.ylabel('購買數量')

在這里插入圖片描述
不難看出,縣越大的購買人數就越多,跟我們的日常理解差不多,

3.1.2.8 探索家庭收入

老套路:

#將51_59列取出來并進行翻譯
data51_59 = chinese(data_01[feature_dict.變數名[51:59].tolist()])
data51_59.head()

在這里插入圖片描述

fre(data51_59)

輸出結果:

欄位名: 是否有房子
----------
欄位資料型別: object
----------------------------
Y    31478
U     4747
P     4604
R     2623
T      204
Name: 是否有房子, dtype: int64
----------------------------
缺失值的個數: 10
------------------------------------------------


欄位名: 是否有醫保補貼
----------
欄位資料型別: object
----------------------------
U    21612
C     8972
A     6765
B     6306
Name: 是否有醫保補貼, dtype: int64
----------------------------
缺失值的個數: 11
------------------------------------------------


欄位名: 收入所處排名
----------
欄位資料型別: float64
----------------------------
79.0    713
61.0    648
55.0    647
82.0    636
88.0    607
       ... 
25.0    258
46.0    254
17.0    246
23.0    225
42.0    162
Name: 收入所處排名, Length: 99, dtype: int64
----------------------------
缺失值的個數: 2
------------------------------------------------


欄位名: 普查家庭有效購買收入
----------
欄位資料型別: int64
----------------------------
48     1034
45      994
44      980
47      967
49      957
       ... 
230       1
198       1
154       1
164       1
191       1
Name: 普查家庭有效購買收入, Length: 208, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 家庭收入
----------
欄位資料型別: float64
----------------------------
49.0     746
46.0     713
63.0     710
59.0     687
60.0     683
        ... 
246.0      1
221.0      1
218.0      1
207.0      1
241.0      1
Name: 家庭收入, Length: 224, dtype: int64
----------------------------
缺失值的個數: 7
------------------------------------------------


欄位名: 家庭房屋價值
----------
欄位資料型別: float64
----------------------------
999.0    1371
138.0     244
168.0     233
125.0     232
175.0     207
         ... 
956.0       1
796.0       1
983.0       1
940.0       1
20.0        1
Name: 家庭房屋價值, Length: 983, dtype: int64
----------------------------
缺失值的個數: 15
------------------------------------------------


欄位名: 社會經濟地位評分
----------
欄位資料型別: int64
----------------------------
77     1194
75     1153
78     1119
80     1119
79     1114
       ... 
166      13
169      12
162      11
165      11
168       8
Name: 社會經濟地位評分, Length: 111, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 家庭自成立日起的時間
----------
欄位資料型別: float64
----------------------------
55.0    3257
56.0    3110
54.0    3034
53.0    2866
57.0    2826
        ... 
28.0       3
25.0       2
26.0       1
81.0       1
20.0       1
Name: 家庭自成立日起的時間, Length: 64, dtype: int64
----------------------------
缺失值的個數: 15
------------------------------------------------
  • 是否有房子:轉成啞變數,同時用眾數填補缺失值;
  • 是否有醫保補貼:轉成啞變數,同時用眾數填補缺失值;
  • 收入所處排名:有缺失值,用中位數填補缺失值;
  • 家庭收入:有缺失值,用中位數填補缺失值;
  • 家庭自成立的時間:有缺失值,用中位數填補缺失值;

接下來我們同樣來查看屬性間的相關性,看看哪些是需要洗掉的,

sns.heatmap(zero_one(data51_59).corr(),cmap='Blues')

在這里插入圖片描述
其實主要就是中間這一部分顏色特別深,

higt_cor(data51_59)

[‘收入所處排名’, ‘普查家庭有效購買收入’, ‘家庭收入’, ‘家庭房屋價值’, ‘社會經濟地位評分’]

從我們的認知來講,這些自然是存在高度相關性的,我們可以考慮保留普查家庭有效購買收入這一個屬性,

3.1.2.9 探索所處地區情況

老套路:

#將59列之后取出來并進行翻譯
data59 = chinese(data_01[feature_dict.變數名[59:].tolist()])
data59.head()

在這里插入圖片描述
很明顯,像這個貧窮以下人的比例和所處地區mobile home的比例這兩個屬性,我們一看就可以知道是相關性很高的,當然其他欄位也是,我們還是用定義好的函式來看一下情況,

fre(data59)

輸出結果為:

欄位名: 該客戶被多少個名單source 包含
----------
欄位資料型別: int64
----------------------------
8     4168
9     4152
10    4131
7     3878
11    3735
6     3654
5     3400
4     3144
3     3044
12    3038
2     2229
13    2017
14    1243
1      728
15     630
16     310
17     104
18      48
19      13
Name: 該客戶被多少個名單source 包含, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 所處的省份
----------
欄位資料型別: object
----------------------------
CA    11700
OH     8959
NY     6481
IN     4954
CT     2873
MO     2202
WI     1884
GA     1687
KY     1375
NH      904
ME      647
Name: 所處的省份, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 貧窮以上人的比例
----------
欄位資料型別: int64
----------------------------
99    4081
98    3624
97    3440
96    3307
95    2885
      ... 
17       1
25       1
35       1
22       1
15       1
Name: 貧窮以上人的比例, Length: 81, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 所處地區有多少居住小區在2000年及以后建立
----------
欄位資料型別: float64
----------------------------
4.0     2467
2.0     2401
3.0     2364
5.0     2317
1.0     2305
        ... 
81.0       5
90.0       4
95.0       4
86.0       3
94.0       2
Name: 所處地區有多少居住小區在2000年及以后建立, Length: 100, dtype: int64
----------------------------
缺失值的個數: 5
------------------------------------------------


欄位名: 所處地區藍領所占百分比
----------
欄位資料型別: int64
----------------------------
18    1717
16    1706
20    1696
17    1679
22    1670
      ... 
61       3
64       2
63       2
67       1
58       1
Name: 所處地區藍領所占百分比, Length: 66, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 貧窮以下人的比例
----------
欄位資料型別: int64
----------------------------
2     3604
3     3464
4     3308
1     3082
5     2884
      ... 
65       1
99       1
83       1
78       1
85       1
Name: 貧窮以下人的比例, Length: 82, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 所處地區mobile home的比例
----------
欄位資料型別: int64
----------------------------
0     33478
1      1677
2      1442
3       906
4       658
      ...  
85        2
66        2
73        1
99        1
78        1
Name: 所處地區mobile home的比例, Length: 96, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 離婚或者分居人群所占比例
----------
欄位資料型別: int64
----------------------------
14    3288
15    3254
16    3162
13    3100
17    3073
12    2826
18    2805
11    2525
19    2345
10    2139
20    2055
9     1727
21    1724
22    1484
8     1228
23    1154
24    1050
7      999
25     656
26     517
6      500
27     414
5      282
28     266
29     199
30     175
31     135
4      130
32     106
0       62
33      56
3       45
34      39
36      38
2       22
35      21
37      13
38      12
42       7
39       6
41       5
1        5
50       4
40       4
55       3
44       2
48       1
47       1
46       1
43       1
Name: 離婚或者分居人群所占比例, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 已婚人群所占比例
----------
欄位資料型別: int64
----------------------------
53    1221
52    1209
48    1164
51    1161
40    1157
      ... 
81       4
79       2
80       2
78       1
82       1
Name: 已婚人群所占比例, Length: 83, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 有房子人所占比例
----------
欄位資料型別: int64
----------------------------
85    972
89    913
88    890
81    877
86    856
     ... 
7     120
3     116
97     69
98      9
99      8
Name: 有房子人所占比例, Length: 100, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 獨宅住戶所占比例
----------
欄位資料型別: float64
----------------------------
99.0    6996
98.0    1213
0.0     1193
97.0    1043
95.0     994
        ... 
14.0     142
19.0     139
17.0     138
27.0     123
24.0     122
Name: 獨宅住戶所占比例, Length: 100, dtype: int64
----------------------------
缺失值的個數: 23
------------------------------------------------


欄位名: 有小孩的家庭所占比例
----------
欄位資料型別: int64
----------------------------
32    1777
33    1754
34    1719
30    1704
31    1690
      ... 
79       2
76       2
99       1
86       1
83       1
Name: 有小孩的家庭所占比例, Length: 86, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 白領所占比例
----------
欄位資料型別: float64
----------------------------
61.0    1198
59.0    1098
63.0    1098
57.0    1072
64.0    1071
        ... 
16.0       3
11.0       2
13.0       1
1.0        1
14.0       1
Name: 白領所占比例, Length: 91, dtype: int64
----------------------------
缺失值的個數: 14
------------------------------------------------


欄位名: 所處地區居住年限
----------
欄位資料型別: float64
----------------------------
19.0    6287
12.0    2756
1.0     2319
17.0    2125
7.0     2013
        ... 
96.0       1
59.0       1
68.0       1
98.0       1
67.0       1
Name: 所處地區居住年限, Length: 70, dtype: int64
----------------------------
缺失值的個數: 6
------------------------------------------------


欄位名: Individual ID
----------
欄位資料型別: int64
----------------------------
142936063    1
68797618     1
193209817    1
172309160    1
171816124    1
            ..
172641155    1
76214763     1
228943803    1
185032198    1
1966080      1
Name: Individual ID, Length: 43666, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: 所在地區處方藥計劃覆寫的比例
----------
欄位資料型別: int64
----------------------------
46    5765
65    2634
47    2518
61    2002
42    1782
      ... 
86       1
88       1
27       1
93       1
95       1
Name: 所在地區處方藥計劃覆寫的比例, Length: 69, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------


欄位名: zip level的家庭收入排名
----------
欄位資料型別: int64
----------------------------
0    6326
9    5119
8    4784
1    4657
7    4191
2    3998
6    3896
3    3611
5    3549
4    3535
Name: zip level的家庭收入排名, dtype: int64
----------------------------
缺失值的個數: 0
------------------------------------------------
  • 所處地區有多少居住小區在2000年及以后建立:有5個缺失值,可以用中位數填充缺失值;

  • 獨宅住戶所占比例:有23個缺失值,可以用中位數填充缺失值;

  • 白領所占比例:有14個缺失值,可以用中位數填充缺失值;

  • 所處地區居住年限:有6個缺失值,可以用中位數填充缺失值;

  • Individual ID:前面就說過啦,可以刪掉這個無用資料;

  • 所在地區處方藥計劃覆寫的比例:和是否有醫療補貼感覺也存在相關性,可以先mark一下;

  • 所處的省份:轉成啞變數,

可以看下省份之間跟購買結果的情況;

sns.countplot(x='STATE_NAME',hue='resp_flag',data=data_01)
plt.xlabel('所處的省份')
plt.ylabel('購買數量')

在這里插入圖片描述
從圖可以看出,我們后面營銷時重點可以放在NY和OH這兩個地方,特別是NY這個地方,

接著我們可以單獨將與人群有關的資料拿出來看下彼此之間的相關性,

a = chinese(data_01[["c210apvt","c210blu","c210bpvt","c210mob","c210wht","zhip19"]])
sns.heatmap(a.corr(),cmap='Blues')

在這里插入圖片描述
可以看到這里還會出現一些負的相關性,主要是因為我們的資料是比例資料,

從產品的目的來講,我們的主要目標人群肯定是貧窮以上的人(窮人都這么窮了,應該不會再花錢購買保險了)

接著我們再呼叫一下方法看下那些相關性高的屬性,

higt_cor(data59)

[‘貧窮以上人的比例’, ‘已婚人群所占比例’, ‘有房子人所占比例’, ‘獨宅住戶所占比例’]

但是這里確實不太適合用這種方法,因為資料主要是比例而不是0-1資料,

當然我們可以看一下所處地區情況的所有欄位之間的相關性:

sns.heatmap(data59.corr(),cmap='brg')

在這里插入圖片描述
這里越綠相關性越好,

我們這里考慮刪掉所處地區藍領所占百分比、貧窮以下人的比例、有房子人所占比例這三個欄位給刪掉,

好,到這里,我們資料探索的程序就搞定了,接下來就是通過資料,將我們做好標記的(哪些是要轉的、哪些是要刪的、哪些是要填充的)資料進行處理,

3.1.3 資料清洗

這里我們還是先備份一下資料:

data_02 = data_01.copy()
data_02.shape

(43666, 76)

3.1.3.1 洗掉特征

我們從EXCEL找出要洗掉的欄位,直接全部刪掉,就不用一個個找啦,

del_col = ["KBM_INDV_ID","U18","POEP","AART","AHCH","AASN","COLLEGE",
 "INVE","c210cip","c210hmi","c210hva","c210kses","c210blu","c210bpvt","c210poo","KBM_INDV_ID","meda"]

data_02 = data_02.drop(columns=del_col)
data_02.shape

(43666, 60)

3.1.3.2 洗掉重復值

我記得我們是沒有發現重復值的,不過一般我們還是會進行這一環節的(而且也很簡單),

data_02.drop_duplicates().shape

(43666, 60)

果然,沒有重復值,

3.1.3.3 劃分訓練集與測驗集

一定要先劃分資料集再填充、轉碼,別急!

from sklearn.model_selection import train_test_split

y = data_02.pop('resp_flag') #標簽
X = data_02  #特征

Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=100)

# 最好還是再備份一下,以防萬一
Xtrain_01=Xtrain.copy()
Xtest_01=Xtest.copy()
Ytrain_01=Ytrain.copy()
Ytest_01=Ytest.copy()

3.1.3.4 填充缺失值

填充中位數

老規矩,我們打開EXCEL,找到我們標記了需要填充中位數的欄位,

fil = ["age","c210mah","c210b200","c210psu","c210wht","ilor"]

Xtrain_01[fil].median()

輸出結果為:

age         71.0
c210mah     53.0
c210b200    10.0
c210psu     77.0
c210wht     61.0
ilor        15.0
dtype: float64
dic = dict(zip(Xtrain_01[fil].median().index,Xtrain_01[fil].median()))
dic

輸出結果為:

{'age': 71.0,
 'c210mah': 53.0,
 'c210b200': 10.0,
 'c210psu': 77.0,
 'c210wht': 61.0,
 'ilor': 15.0}
#向訓練集填充中位數
Xtrain_01 = Xtrain_01.fillna(dic) 

填充眾數

基本同樣的操作:

mod = ["N1819","ASKN","MOBPLUS","N2NCY","LIVEWELL","HOMSTAT","HINSUB"]

dic_mod = dict(zip(Xtrain_01[mod].mode().columns,Xtrain_01[mod].iloc[0,:]))

Xtrain_01 = Xtrain_01.fillna(dic_mod) 

替換填充

這里可不要忘了我們最開始發現的0換N,

Xtrain_01['N6064'] = Xtrain_01['N6064'].replace('0','N')  #0  替換成  N

Xtrain_01.isnull().sum()[Xtrain_01.isnull().sum()!=0]

Series([], dtype: int64)

對測驗集進行填充(總結)

這里測驗集也是一樣的方式:

# 需要填的欄位
fil = ["age","c210mah","c210b200","c210psu","c210wht","ilor"]

#填充中位數--測驗集

dic = dict(zip(Xtest_01[fil].median().index,Xtest_01[fil].median()))

Xtest_01 = Xtest_01.fillna(dic) 

# #填充眾數--測驗集
mod = ["N1819","ASKN","MOBPLUS","N2NCY","LIVEWELL","HOMSTAT","HINSUB"]

dic_mod = dict(zip(Xtest_01[mod].mode().columns,Xtest_01[mod].iloc[0,:]))

Xtest_01 = Xtest_01.fillna(dic_mod) 

# #替換填充
Xtest_01['N6064'] = Xtest_01['N6064'].replace('0','N') 

Xtest_01.isnull().sum()[Xtest_01.isnull().sum() !=0]

3.1.4 轉碼

打開我們記錄好的EXCEL檔案,找到需要進行轉碼的資料,

不過我們可以發現確實是有點多,就不適合一個個復制出來啦,我們可以寫一個方法,讀取EXCEL檔案,把變數名和轉碼的兩列欄位復制到另一個sheet里,方便讀取,

encod_col = pd.read_excel('保險案例資料字典_清洗.xlsx',sheet_name=2)
encod_col.head()

在這里插入圖片描述

# 查看Xtrain_01中object型別
object_tr =Xtrain_01.describe(include='O').columns
object_tr

輸出結果為:

Index(['GEND', 'ADBT', 'ADEP', 'AHBP', 'ARES', 'AHRT', 'ADGS', 'AHRL', 'ASKN',
       'AVIS', 'BANK', 'FINI', 'INLI', 'INMEDI', 'IOLP', 'MOBPLUS', 'N2NCY',
       'N1819', 'N2029', 'N3039', 'N4049', 'N5059', 'N6064', 'N65P', 'ONLA',
       'SGFA', 'SGLL', 'SGOE', 'SGSE', 'SGTC', 'POC19', 'HOMSTAT', 'HINSUB',
       'STATE_NAME'],
      dtype='object')
#檢查一下轉碼的目標是否出現
np.setdiff1d(object_tr,encod_col['變數名'])

array([], dtype=object)

3.1.4.1 0-1轉碼

# 獲取0-1 轉碼的變數名
z_0_list = encod_col[encod_col['轉']=='0-1'].變數名
z_0_list.head()

輸出結果為:

0     GEND
3    N1819
4    N2029
5    N3039
6    N4049
Name: 變數名, dtype: object
# 重新定義一個Xtrain_02,用于轉碼
Xtrain_02 = Xtrain_01[z_0_list]
Xtrain_02.head()

在這里插入圖片描述

#sklearn的預處理模塊
from sklearn.preprocessing import OrdinalEncoder

#fit_transform 直接轉
new_arr = OrdinalEncoder().fit_transform(Xtrain_02)
new_arr

在這里插入圖片描述
下面我們來做下合并,

# columns 設定表頭為原來的   index 索引也是原來
Xtrain_02 = pd.DataFrame(data=new_arr,columns=Xtrain_02.columns,index=Xtrain_02.index)
Xtrain_02.head()

在這里插入圖片描述
將轉好的Xtrain_02 0-1編碼變數 替換掉Xtrain_01:

Xtrain_01[z_0_list] = Xtrain_02

Xtrain_01.head()

在這里插入圖片描述

3.1.4.2 啞變數轉碼

注意:啞變數轉碼有兩種方法,一種是pandas中的get_dummies方法,另一種是sklearn中的onehot方法,區別主要在于pandas中的方法只能處理字符變數不能處理數值變數,而sklearn都可以,所以如果用get_dummies處理數值型資料的話得先將數值型資料轉換成字符型資料,

下面我們用get_dummies來實作轉碼,

#獲取啞變數---轉碼的變數名

o_h_list = encod_col[encod_col['轉']=='啞變數'].變數名
o_h_list

輸出結果為:

1        c210mys
2          POC19
24       MOBPLUS
25         N2NCY
32      LIVEWELL
33       HOMSTAT
34        HINSUB
35    STATE_NAME
Name: 變數名, dtype: object
Xtrain_01[o_h_list].head()

在這里插入圖片描述

o_h_01 = ['c210mys','LIVEWELL'] #非字符型的變數
o_h_02 = [i for i in o_h_list if i not in o_h_01] #字符型別的變數

#先轉o_h_02
Xtrain_02 = Xtrain_01.copy()
chinese(Xtrain_02[o_h_02]).head()

在這里插入圖片描述

Xtrain_02 = pd.get_dummies(chinese(Xtrain_02[o_h_02]))
Xtrain_02.head()

在這里插入圖片描述

#w我們再轉 o_h_01
Xtrain_03 = Xtrain_01.copy()

#轉成字符型別
Xtrain_03 = Xtrain_03[o_h_01].astype(str)
#轉化覆寫
Xtrain_03 = pd.get_dummies(chinese(Xtrain_03[o_h_01]))

Xtrain_03.head()

在這里插入圖片描述
Xtrain_02 Xtrain_03 是轉好的 先洗掉原轉碼的欄位再將轉好的插入到資料集中,

# Xtrain_04 洗掉原轉碼的欄位
Xtrain_04 = Xtrain_01.copy() 
Xtrain_04 = chinese(Xtrain_04.drop(columns=o_h_01+o_h_02))
Xtrain_04.head()

在這里插入圖片描述

Xtrain_04.shape

(30566, 51)

Xtrain_02.shape #字符的啞變數

(30566, 31)

Xtrain_03.shape #非字符的啞變數

(30566, 14)

#將 Xtrain_04  Xtrain_02 Xtrain_03 合并
Xtrain_05 = pd.concat([Xtrain_04,Xtrain_02,Xtrain_03],axis=1)
Xtrain_05.shape

(30566, 96)

Xtrain_05.head()

在這里插入圖片描述

3.1.4.3 對測驗集進行轉碼(總結)

0-1 轉碼總結:

#獲取需要轉碼的欄位
encod_col = pd.read_excel('保險案例資料字典_清洗.xlsx',sheet_name=2)

# 查看Xtest_01中object型別
object_tr =Xtest_01.describe(include='O').columns

#檢查一下轉碼的目標是否出現
np.setdiff1d(object_tr,encod_col['變數名'])

#0-1 轉碼
# 獲取0-1 轉碼的變數名
z_0_list = encod_col[encod_col['轉']=='0-1'].變數名

Xtest_02 = Xtest_01[z_0_list]

#sklearn的預處理模塊
from sklearn.preprocessing import OrdinalEncoder

#fit_transform 直接轉
new_arr = OrdinalEncoder().fit_transform(Xtest_02)
# columns 設定表頭為原來的   index 索引也是原來
Xtest_02 = pd.DataFrame(data=new_arr,columns=Xtest_02.columns,index=Xtest_02.index)

Xtest_01[z_0_list] = Xtest_02

Xtest_01.head()

在這里插入圖片描述
啞變數 總結

#獲取啞變數轉碼的變數
o_h_list = encod_col[encod_col['轉']=='啞變數'].變數名

o_h_01 = ['c210mys','LIVEWELL'] #非字符型的變數
o_h_02 = [i for i in o_h_list if i not in o_h_01] #字符型別的變數

#先轉o_h_02 字符型別
Xtest_02 = Xtest_01.copy()
Xtest_02 = pd.get_dummies(chinese(Xtest_02[o_h_02]))

#w我們再轉 o_h_01  非字符
Xtest_03 = Xtest_01.copy()
#轉成字符型別
Xtest_03 = Xtest_03[o_h_01].astype(str)
#轉化覆寫
Xtest_03 = pd.get_dummies(chinese(Xtest_03[o_h_01]))


# Xtrain_04 洗掉原轉碼的欄位
Xtest_04 = Xtest_01.copy() 
Xtest_04 = chinese(Xtest_04.drop(columns=o_h_01+o_h_02))


#將 Xtest_04  Xtest_02 Xtest_03 合并
Xtest_05 = pd.concat([Xtest_04,Xtest_02,Xtest_03],axis=1)
Xtest_05.shape

(13100, 96)

Xtest_05.head()

在這里插入圖片描述

3.1.5 資料建模與評估

3.1.5.1 初步建模

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score

clf = DecisionTreeClassifier(random_state=420,class_weight='balanced')
cvs = 
cross_val_score(clf,Xtrain_05,Ytrain)

cvs.mean()

0.5993914576104883

3.1.5.2 網格搜索找最優引數

from sklearn.model_selection import GridSearchCV

#測驗引數
param_test = {
             'splitter':('best','random'),
             'criterion':('gini','entropy'), #基尼  資訊熵
             'max_depth':range(3,15) #最大深度
             #,min_samples_leaf:(1,50,5)
}

gsearch= GridSearchCV(estimator=clf, #對應模型
                param_grid=param_test,#要找最優的引數
                scoring='roc_auc',#準確度評估標準 
                n_jobs=-1,# 并行數  個數   -1:跟CPU核數一致
                cv = 5,#交叉驗證 5折
                iid=False,# 默認是True  與各個樣本的分布一致 
                verbose=2#輸出訓練程序
                )

gsearch.fit(Xtrain_05,Ytrain_01)

輸出結果如下:

GridSearchCV(cv=5,
             estimator=DecisionTreeClassifier(class_weight='balanced',
                                              random_state=420),
             iid=False, n_jobs=-1,
             param_grid={'criterion': ('gini', 'entropy'),
                         'max_depth': range(3, 15),
                         'splitter': ('best', 'random')},
             scoring='roc_auc', verbose=2)
#優化期間觀察到的最高評分
gsearch.best_score_

0.691856415170639

gsearch.best_params_

{‘criterion’: ‘entropy’, ‘max_depth’: 6, ‘splitter’: ‘best’}

3.1.5.3 模型評估

from sklearn.metrics import accuracy_score #準確率
from sklearn.metrics import precision_score #精準率
from sklearn.metrics import recall_score #召回率
from sklearn.metrics import roc_curve
y_pre = gsearch.predict(Xtest_05)

accuracy_score(y_pre,Ytest) 

0.6090076335877863

precision_score(y_pre,Ytest)

0.748152359295054

recall_score(y_pre,Ytest)

0.5100116264048572

接下來我們來畫圖看一下ROC曲線:

fpr,tpr,thresholds = roc_curve(y_pre,Ytest) #roc引數
import matplotlib.pyplot as plt

plt.plot(fpr,tpr,c='b',label='roc曲線')
plt.plot(fpr,fpr,c='r',ls='--')

在這里插入圖片描述
所以綜上來看,我們的模型效果算是不好不壞吧,

3.1.5.4 輸出規則

#最優引數
#{'criterion': 'entropy', 'max_depth': 6, 'splitter': 'best'}
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree

import graphviz

#將最優引數放到分類器
clf = DecisionTreeClassifier(criterion='entropy',max_depth=6,splitter='best')
clf = clf.fit(Xtrain_05,Ytrain)


features = Xtrain_05.columns
dot_data = tree.export_graphviz(clf,
                     feature_names=features,
                     class_names=['Not Buy','Buy'],
                     filled=True,
                     rounded=True,
                     leaves_parallel=False)

graph= graphviz.Source(dot_data)

graph

我們來看下圖:
在這里插入圖片描述

3.1.6 輸出結果的商業應用

我們來看一下購買比例最高的兩類客戶的特征是什么?

結合上圖,我們只要看藍色的部分,可以得到以下結果,

3.1.6.1 第一類

  • 處于醫療險覆寫率比例較低區域
  • 居住年限小于7年
  • 65-72歲群體

那么我們對業務人員進行建議的時候就是,建議他們在醫療險覆寫率比例較低的區域進行宣傳推廣,然后重點關注那些剛到該區域且年齡65歲以上的老人,向這些人群進行保險營銷,成功率應該會更高,

3.1.6.2 第二類

  • 處于醫療險覆寫率比例較低區域
  • 居住年限大于7年(小于)年
  • 居住房屋價值較高

這一類人群,是區域內常住的高端小區的用戶,這些人群也同樣是我們需要重點進行保險營銷的物件,

除此之外,我們還可以做些什么?

3.1.6.3 了解客戶需求

我們需要了解客戶的需求,并根據客戶的需求舉行保險營銷,PIOS資料∶向客戶推薦產品,并利用個人的資料(個人特征)向客戶推薦保險產品,旅行者∶根據他們自己的資料(家庭資料),生活階段資訊推薦的是財務保險、人壽保險、保險、舊保險和用戶教育保險,外部資料、資產保險和人壽保險都提供給高層人士,利用外部資料,我們可以改進保險產品的管理,增加投資的收益,

3.1.6.4 開發新的產品

保險公司還應協助外部渠道開發適合不同商業環境的保險產品,例如新的保險型別,如飛行延誤保險、旅行時間保險和電話盜竊保險,目的是提供其他保險產品,而不是從這些保險中受益,而是尋找潛在的客戶,此外,保險公司將通過資料分析與客戶聯系,了解客戶,外部因素將降低保險的營銷成本,并直接提高投資回報率,

結束語

本次專案真的非常非常的詳細,從這次專案我們也不難發現,資料探索和可視化這一部分是最花時間的,而這一部分也就是為了資料清洗來服務的(當然最終也可以結合可視化得到的結論),后續建模部分反而花的工夫不是很多,因為資料質量的好壞其實是決定最終效果的最大因素,如果我們不先了解清楚資料并進行清洗轉換,后續作業也變得沒有什么意義,

總之,程序雖然繁瑣,但也飽含著樂趣,能從繁瑣的資料中得到更多有用的結論,也顯得那么的有意義,

CSDN@報告,今天也有好好學習

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300673.html

標籤:AI

上一篇:機器學習演算法學習01:利用Numpy撰寫KNN演算法解決手寫體數字識別問題

下一篇:26.疲勞檢測

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more