保险索赔分析

一、基本情况

  保险业有着大量的数据,对其中蕴含的信息,需要通过数据分析和挖掘的手段进行提取,并应用于客户分析、产品分析、理赔分析、风险控制等诸多方面。

  本文利用一份包含约2万条索赔信息的保险数据集进行分析和挖掘。其中每一条信息涵盖索赔额、赔付额、渠道、地域以及客户的性别、年龄等。主要考查支付额、索赔额以及两者的比值(在本文中称其为支索比)这几项指标的基本特征以及影响因素。然后利用机器学习建立用户画像。

 

二、数据初探

1.先看索赔额、支付额以及支索比三项指标的大致情况。

支付额约90%集中在1200元以内,低于650元的占比约75%,值得注意的是,为0元的占比接近40%。

索赔额则约90%集中在1900元以内,低于1300元的占比约75%,中位数是825元。

支索比约50%集中在0.58-0.78之间, 为0的有40%(同支付额),其它部分占比约10%。

 

 

2.然后来看不同区域的情况

上图第一张是支付及索赔的总额,第二张是平均值。可以通过对比看出各省的情况。比如广东的总额高,但平均值低,则可以初步判断,广东省有较多的优质客户。

从区域上看,支索比由高到低依次是华南>华东>华北>东北>中南>西北>西南。

 

 有一项特征为“服务中心”,其分析与对不同地区的分析过程基本相同,后面不赘述。

 

3.再考查各指标随时间的变化情况。在tableau仪表板中,我们通过设计,显示指定地域和指标随时间变化情况。此处仅以华南&西南的平均支付额随时间变化为例进行说明,见下图:

在2011年1月30-3月21日期间,华南地区人均支付额以12.8元/日的增幅上升,西南地区人均支付额则以3.2元/日的幅度下降。

 

4.查看不同年龄客户的差别,发现平均支付额和支索比随年龄变化的增减趋势并不明显,暂时判定年龄不是主要影响因素。

 

 5.性别因素的影响。

 

 

可以看出,男性的索赔额、支付额、支索比均略高于女性,但差别不大。

 

6.客户提交索赔的渠道有通过医生、手机、网络三种。不同渠道的客户索赔情况。从总额来看,使用渠道比例由高到低依次是网络、手机、医生。通过医生的比例较少,而支索比偏高。原因可能是,通过该渠道的客户具备较好的经济条件,能够得到相对充分的建议。通过手机端的客户支索比则明显较低,分析其原因,由于手机操作的便利,该类客户在发起索赔时可能具有更大的随意性。

 

 

三、机器学习对客户进行分类(用户画像)

根据前面的分析,按照支索比为0,0-0.58,0.58-0.78,0.78-1将客户分为4类。选取省份、索赔渠道、性别,服务中心为基本特征组合,用k-邻近分类算法预测各种条件的客户会属于哪一类。

各项特征及客户类别转为整数值表示,同时将支索比缺失项定义为一个整数值。用交叉验证来观察模型的效果。设置两层循环,一层选取k折交叉验证中的最优k值,一层从基本特征组合中选取最佳组合。

最后得到的结果,在14折交叉验证下取得0.56的平均准确率,基本特征组合即为最优特征组合。考虑到原始数据中可用于建模的特征数量及与支索比的相关程度,这样的结果基本达到预期效果。

python代码如下:

import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.neighbors import KNeighborsClassifier

# plt.rcParams['font.sans-serif'] = ['SimHei']                 # 用来正常显示中文标签
# plt.rcParams['axes.unicode_minus'] = False                   # 用来正常显示负号
pd.set_option('display.width', 500, 'display.max_rows', 100, 'display.max_columns', None)  # 设置数据显示


data=pd.read_excel("../data/data.xls")                          # 导入数据

# 省级数据整数化
tmp1=data["省级"].drop_duplicates(keep='first').values              # 取出省级列数据,去重,返回数组
size_mapping1={}
for i in range(0,len(tmp1)):
    size_mapping1[tmp1[i]]=i                                                 # 字典,省级映射为整数
# print(size_mapping)
data["省级"] = data["省级"].map(size_mapping1)                               # 将省级列根据映射转为整数


# 服务中心数据整数化
tmp2=data["服务中心"].drop_duplicates(keep='first').values              # 取出服务中心列数据,去重,返回数组
size_mapping2={}
for i in range(0,len(tmp2)):
    size_mapping2[tmp2[i]]=i                                             # 字典,服务中心映射为整数
data["服务中心"] = data["服务中心"].map(size_mapping2)                   # 将服务中心列根据映射转为整数


# 性别数据整数化
data["性别"][data["性别"]==""]=0
data["性别"][data["性别"]==""]=1

# 渠道数据整数化
data["源代码"][data["源代码"]=="网络"]=0
data["源代码"][data["源代码"]=="手机"]=1
data["源代码"][data["源代码"]=="医生"]=2

# 支索比分组
data["支索比"]=data["总支付额"]/data["总索赔额"]
data["支索比"][data["支索比"]>=0.78]=3
data["支索比"][(data["支索比"]>0.58) & (data["支索比"]<=0.78)]=2
data["支索比"][(data["支索比"]>0) & (data["支索比"]<0.58)]=1
data["支索比"][data["支索比"]==0]=0
data["支索比"].notnull().astype(int)                                           # 转为整数

# k-折交叉验证
def c_validation(k):
    z=["省级","性别","源代码","服务中心"]
    score=[]                  # 记录评分的列表
    temp0=[]                  # 记录当前选取的特征组合的评分
    temp1=0                   # 记录当前选取组合的平均分数
    temp2=0                   # 记录当前选取组合的分数标准差
   
    import itertools
    for j in range(1,5):
        for i in itertools.combinations(z, j):                     # 取包含j个属性的特征组合
            i=list(i)

            from sklearn import cross_validation
            from sklearn.model_selection import cross_val_score
            knc_kf=KNeighborsClassifier()                          # 定义一个k-邻近分类器
            x =data[i]                                             # ["省级","性别","服务中心","源代码"]
            y =data["支索比"].fillna(100)                           # null填充为100
            score=cross_val_score(knc_kf, x, y, cv=k)              # 交叉验证分数列表

            if (score.mean() > temp1 and score.std() < 0.08):  # 特征组合选取条件,标准差在指定范围,平均分最大
                temp0 = score
                temp1 = score.mean()
                temp2 = score.std()
                dict = {temp1: i}
    return dict, temp0, temp1, temp2

score_k=0
for k in range(5,17):
    print(k)
    c_vl=c_validation(k)
    if c_vl[-2]>score_k:
        score_k=c_vl[-2]
        c_vlm=c_vl
        k_m=k
print(score_k,c_vlm,k_m)

 

 

数据来源:tableau社区http://www.tableauhome.com.cn/

 

posted @ 2018-09-13 09:52  todaynowind  阅读(793)  评论(0)    收藏  举报