一、产品介绍
针对65岁以上的人群推出的医疗附加险,销售渠道为直邮。
二、商业目的
针对保险公司的健康险产品的用户数据,制作用户画像,找出最具有购买倾向的人群以进行精准保险营销。
三、分析流程
1 导入数据,观察数据
···了解数据样本和特征个数、数据类型、基本信息等
df.shapedf.dtypes# 将ID转换成objectdf['KBM_INDV_ID'] = df['KBM_INDV_ID'].astype('object')
···统计数据基本信息
df.describe().T
···统计空值数量
# 检查缺失列的数量len(df.columns) - df.dropna(axis=1).shape[1]# 统计各列中空值的数量df_null_sum = df.isnull().sum()# 将不为零的数据过滤出来NA = df.isnull().sum()NA = NA.reset_index()NA# 重置列名NA.columns = ['Var','NA_count']NA# 过滤出大于0的数据NA = NA[NA.NA_count>0].reset_index(drop=True)NA# 把空值个数,换算成比例NA.NA_count/df.shape[0]
···查看数据中是否有重复值
df[df.duplicated()]
2 探索数据及数据可视化分析
import matplotlib.pyplot as pltimport seaborn as snsplt.style.use('seaborn')# 支持中文plt.rcParams['font.sans-serif']=['SimHei']plt.rcParams['axes.unicode_minus']=False
···探索样本分类是否均衡
plt.figure(figsize=(10,3))sns.countplot(y='resp_flag',data=df)plt.show()
···计算购买用户和未购买用户的比例
df.resp_flag.sum()/df.resp_flag.shape[0]1- df.resp_flag.sum()/df.resp_flag.shape[0]
···用户年龄分布情况
sns.distplot(df['age'],bins=20)
···探索用户年龄和购买商业医疗保险之间的关系
sns.kdeplot(df.age[df.resp_flag==1],label='1',shade=True)sns.kdeplot(df.age[df.resp_flag==0],label='0',shade=True)plt.xlim([60,90])plt.xlabel('age')plt.ylabel('Density')
···查看性别比例
plt.figure(figsize=(10,3))sns.countplot(y = 'GEND',data=df)plt.show()
···学历情况
df.c210mys.value_counts()plt.figure(figsize=(10,3))sns.countplot(y='c210mys',data=df)plt.show()
···查看不同的学历之间是否购买保险的人数
sns.countplot(x='c210mys',hue='resp_flag',data=df)plt.xlabel('学历')plt.ylabel('购买数量')
···不同的县级别是否购买保险的人数
sns.countplot(x='N2NCY',hue='resp_flag',data=df)plt.xlabel('县的大小')plt.ylabel('购买数量')
3 空值填充
···探索数据中有哪些特征含有空值
# 统计每一列数据类型NA.Vartemp=[]for i in NA.Var:temp.append(df[i].dtypes)NA['数据类型']=temp
···空值填充策略:
分类变量:通常分类水平出现的次数多,出现的概率就是最高的。用众数来填充。
数值型变量:幸福指数 收入所处排名都是分类变量
# 去掉年龄NA[NA.Var!='age'].Var# 对列名进行遍历,依次进行填充for i in NA[NA.Var!='age'].Var:df[i].fillna(df[i].mode()[0],inplace=True)# 年龄采用均值填充df.age.fillna(df.age.mean(),inplace=True)
4 变量编码
···将无效特征删除
# 首先把用户ID删除del df['KBM_INDV_ID']
···分类变量进行数值化编码
df_object = df.select_dtypes('object')from sklearn.preprocessing import OrdinalEncoderdf_object = OrdinalEncoder().fit_transform(df_object)# 进行数据的编码转换for i in df.columns:if df[i].dtypes=='object':df[i]=OrdinalEncoder().fit_transform(df[[i]])
5 数据建模
···切分数据集
X = df.iloc[:,1:]y = df['resp_flag']Xtrain,Xtest,Ytrain,Ytest=train_test_split(X,y,test_size=0.3,random_state=420)
···建模
clf = tree.DecisionTreeClassifier()clf.fit(Xtrain,Ytrain)clf.score(Xtest,Ytest)#0.5946
···网格搜索 尝试使用最小叶节点样本数量和最小分割样本数量进行调参
from sklearn.model_selection import GridSearchCVparam_grid = {'min_samples_leaf':list(range(1000,6000,100)),'min_samples_split':list(range(4000,6000,100))}GR = GridSearchCV(tree.DecisionTreeClassifier(),param_grid,cv=5)GR.fit(Xtrain,Ytrain)GR.best_params_ # leaf 1500, split 4000
clf = tree.DecisionTreeClassifier(criterion='gini',max_depth=4,min_samples_leaf=1500,min_samples_split=4000)clf.fit(Xtrain,Ytrain)clf.score(Xtest,Ytest)#0.65
···画出树
import graphvizfeatures = list(df.columns[1:])dot_data = tree.export_graphviz(clf,feature_names=features,class_names=['NP','P'],filled=True,rounded=True)graph = graphviz.Source(dot_data)graph# 输出PDF文件graph.render('model1')
四、输出结果的业务应用
购买比例最高的两类客户的特征
第一类
处于医疗保险覆盖率比例较低的区域居住年限小于7年65-72岁群体
建议业务人员在医疗保险覆盖率比例较低的区域进行宣传推广,重点关注那些刚到该区域且年龄65岁以上的老人,向这些人群进行保险营销,成功率应该会更高。
第二类
处于医疗保险覆盖率比例较低的区域居住年限大于7年居住房屋价值较高
这类人群是区域内常住高端小区的用户。同样是我们需要重点进行保险营销的对象。