2022 年“泰迪杯”数据分析技能赛B 题银行客户忠诚度分析

2022 年“泰迪杯”数据分析技能赛B 题银行客户忠诚度分析

完整代码请私聊 博主

一、背景

目前银行产品存在同质化现象,客户选择产品和服务的途径越来越多,对产品的忠诚度越来越低。为了提高客户对银行的忠诚度和银行营销量,商业银行迫切需要转变经营理念,从“产品销售导向”业务模式向“以客户为中心”转变,为客户带来极致体验和价值成长,形成路径依赖,进而实现价值共赢。
客户忠诚度主要体现为客户的行为和态度。客户行为主要表现为产品重复购买的频率,而客户态度主要表现为情感的倾向。为了有效挖掘客户忠诚度,需要从短期客户产品购买数据和长期客户资源信息中分析客户需求指标。其中,短期客户忠诚度分析是通过产品的购买数据,分析不同指标客户对银行产品的购买依赖度从而提供更好的销售服务;长期客户忠诚度分析则是从客户资源信息数据中挖掘客户流失因素、预测可能流失的客户,尽可能留住高价值客户。

二、数据说明

银行客户忠诚度分析数据包括短期客户产品购买数据和长期客户资源信息数据,附件数据详细情况如表 1 所示。
在这里插入图片描述

短期客户产品购买数据记录了往期银行营销活动中客户购买产品的信息,包含客户的基本信息、上次活动后拜访客户信息和上次活动产品购买结果等,具体的数据指标说明如表 2 所示。
在这里插入图片描述
长期客户资源信息数据记录了往期该银行客户流动状态及客户信息,包括客户基本信息、客户户龄与金融资产、客户活跃状态与流失情况等,具体的数据指标说明如表 3 所示。

在这里插入图片描述

三、目标

(1) 对客户数据进行预处理,并对字符型数据进行特征编码。
(2) 基于短期客户产品购买数据,分析不同指标客户对银行产品的购买依
赖度,并进行可视化呈现。
(3) 基于长期客户资源信息数据,分析客户流失因素,并进行可视化呈现。
(4) 依据长期客户资源信息数据的分析结果构建相关指标,对银行客户长
期忠诚度进行预测。

四、任务

任务 1 数据探索与清洗

分别对短期客户产品购买数据“short-customer-data.csv”(简称短期数据)和长期客户资源信息数据的训练集“long-customer-train.csv”(简称长期数据)进行数据探索与清洗。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pyecharts.charts import Bar
from pyecharts.globals import ThemeType 
import seaborn as sns
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False

任务 1.1 数据探索与预处理

(1) 探索短期数据各指标数据的缺失值和“user_id”列重复值,删除缺失值、重复值所在行数据。请在报告中给出处理过程及必要结果,完整的结果保存到文件“result1_1.xlsx”中。

df = pd.read_csv('short-customer-data.csv')
df.head()
df.info()
df.describe()
df.isnull().sum()
df.dropna(inplace=True)
df.isnull().sum()
df.duplicated(subset=['user_id']).sum()
df.drop_duplicates('user_id',keep='first',inplace=True)
df.reset_index(inplace=True,drop=True) 
df.to_excel('result1_1.xlsx',index=None)
df

(2) 长期数据中的客户年龄“Age”列存在数值为-1、0 和“-”的异常值,删除存在该情况的行数据;“Age”列存在空格和“岁”等异常字符,删除这些异常字符但须保留年龄数值,将处理后的数值存于“Age”列。请在报告中给出处理过程及必要结果,完整的结果保存到文件“result1_2.xlsx”中。

df2 = pd.read_csv('long-customer-train.csv')
df2
df2 = df2.loc[(df2['Age']!='-1')&(df2['Age']!='0')&(df2['Age']!='-')]
df2


	CustomerId	CreditScore	Gender	Age	Tenure	Balance	NumOfProducts	HasCrCard	IsActiveMember	EstimatedSalary	Exited
0	15553251	713	1	52	0	185891.54	1	1	1	46369.57	1
1	15553256	619	1	41	8	0.00	3	1	1	79866.73	1
2	15553283	603	1	42	8	91611.12	1	0	0	144675.30	1
3	15553308	589	1	61	1	0.00	1	1	0	61108.56	1
4	15553387	687	1	39	2	0.00	3	0	0	188150.60	1
...	...	...	...	...	...	...	...	...	...	...	...
9295	15815628	711	1	37	8	113899.92	1	0	0	80215.20	0
9296	15815645	481	0	37	8	152303.66	2	1	1	175082.20	0
9297	15815656	541	1	39	9	100116.67	1	1	1	199808.10	1
9298	15815660	758	1	34	1	154139.45	1	1	1	60728.89	0
9299	15815690	614	1	40	3	113348.50	1	1	1	77789.01	0
9198 rows × 11 columns
def clean(x):
    return int(x.replace(' ','').replace('岁',''))
df2['Age'] = df2['Age'].apply(lambda x:clean(x))
df2.to_excel('result1_2.xlsx',index=None)
	CustomerId	CreditScore	Gender	Age	Tenure	Balance	NumOfProducts	HasCrCard	IsActiveMember	EstimatedSalary	Exited
300	15565701	698	1	39	9	161993.89	1	0	0	90212.38	0
302	15565714	601	0	47	1	64430.06	2	0	1	96517.97	0
303	15565779	627	1	30	6	57809.32	1	1	0	188258.49	0
304	15565796	745	0	48	10	96048.55	1	1	0	74510.65	0
305	15565806	532	0	38	9	0.00	2	0	0	30583.95	0
...	...	...	...	...	...	...	...	...	...	...	...
9191	15815615	681	0	36	5	141952.07	1	1	1	185144.08	0
9193	15815628	711	1	37	8	113899.92	1	0	0	80215.20	0
9194	15815645	481	0	37	8	152303.66	2	1	1	175082.20	0
9196	15815660	758	1	34	1	154139.45	1	1	1	60728.89	0
9197	15815690	614	1	40	3	113348.50	1	1	1	77789.01	0

任务 1.2

对短期数据中的字符型数据进行特征编码,如将信用违约情况{‘否’,‘是’}编码为{0,1}。请在报告中给出处理思路、过程及必要结果,完整的结
果保存到文件“result1_3.xlsx”中。

df4 = pd.read_excel('result1_1.xlsx')
df4.head()
df4.columns
for k in['job','marital','education','default','housing','loan','contact','month','day_of_week','poutcome','y']:
    m = {}
    for i,j in enumerate(df4[k].unique()):
        m[j] = i
    print(m)
    df4[k] = df4[k].map(m)
df4.to_excel('result1_3.xlsx')
df4.head()
	user_id	age	job	marital	education	default	housing	loan	contact	month	day_of_week	duration	poutcome	y
0	BA2200001	56	0	0	0	0	0	0	0	0	0	261	0	0
1	BA2200077	37	1	0	1	0	1	0	0	0	0	226	0	0
2	BA2200004	40	2	0	0	0	0	0	0	0	0	151	0	0
3	BA2200005	56	1	0	1	0	0	1	0	0	0	307	0	0
4	BA2200007	59	2	0	2	0	0	0	0	0	0	139	0	0

任务 2 产品营销数据可视化分析

基于短期数据分析不同指标客户与购买银行产品行为的关联性,挖掘短期客户对银行的忠诚度。

任务 2.1

计算短期数据所有指标之间的相关性,绘制相关系数热力图,并在报告中对结果进行必要分析。

plt.figure(figsize=(13,10))
corr = df4.iloc[:,1:].corr()
sns.heatmap(corr,annot=True,fmt='.2f',cmap='rainbow')
plt.title('相关系数热力图')
plt.show()

在这里插入图片描述

任务 2.2

在同一画布中,绘制反映两种产品购买结果下不同年龄客户量占比的分组柱状图,x 轴为年龄,y 轴为占比数值,并在报告中对结果进行必要分析。

y	0	1
age		
[0, 20)	0.000790	0.004149
[20, 30)	0.147241	0.201504
[30, 40)	0.454361	0.387189
[40, 50)	0.239460	0.170124
[50, 60)	0.139042	0.140560
[60, 70)	0.011358	0.052645
[70, 80)	0.005566	0.029564
[80, 90)	0.002031	0.014263
[90, 100)	0.000150	0.000000

在这里插入图片描述

任务 2.3

在同一画布中,绘制蓝领(blue-collar)与学生(student)的产品购买情况饼图,并设定饼图的标签,显示产品购买情况的占比。

# 将工作类型转换为字符串,便于识别
df4['job_str'] = df4['job'].map({0: 'admin.', 1: 'blue-collar', 2: 'entrepreneur',
                                3: 'housemaid', 4: 'management', 5: 'retired',
                                6: 'self-employed', 7: 'services', 8: 'student',
                                9: 'technician', 10: 'unemployed'})

在这里插入图片描述

任务 2.4

以产品购买结果为 x 轴、拜访客户的通话时长为 y 轴,绘制拜访客户的通话时长箱线图,并在报告中对结果进行必要分析。

在这里插入图片描述

df4
	user_id	age	job	marital	education	default	housing	loan	contact	month	day_of_week	duration	poutcome	y	age_group	job_str
0	BA2200001	56	0	0	0	0	0	0	0	0	0	261	0	0	[50, 60)	admin.
1	BA2200077	37	1	0	1	0	1	0	0	0	0	226	0	0	[30, 40)	blue-collar
2	BA2200004	40	2	0	0	0	0	0	0	0	0	151	0	0	[40, 50)	entrepreneur
3	BA2200005	56	1	0	1	0	0	1	0	0	0	307	0	0	[50, 60)	blue-collar
4	BA2200007	59	2	0	2	0	0	0	0	0	0	139	0	0	[50, 60)	entrepreneur
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
30440	BA2241171	29	5	1	0	0	1	0	1	5	4	112	2	0	[20, 30)	retired
30441	BA2241173	46	4	0	2	0	0	0	1	5	4	383	0	0	[40, 50)	management
30442	BA2241174	56	6	0	3	0	1	0	1	5	4	189	0	0	[50, 60)	self-employed
30443	BA2241175	44	3	0	2	0	0	0	1	5	4	442	0	1	[40, 50)	housemaid
30444	BA2241176	74	6	0	2	0	1	0	1	5	4	239	1	0	[70, 80)	self-employed
30445 rows × 16 columns

任务 3 客户流失因素可视化分析

基于长期数据分析导致银行客户流失的因素,并进行可视化呈现。

任务 3.1

在同一画布中,绘制反映两种流失情况下不同年龄客户量占比的折线图,x 轴为年龄,y 轴为占比数值。

在这里插入图片描述

任务 3.2

在同一画布中,绘制反映两种流失情况下客户信用资格与年龄分布的散点图,x 轴为年龄,y 轴为信用资格。

在这里插入图片描述

任务 3.3

构造包含各账号户龄在不同流失情况下的客户量占比透视表(详见表 4),并在同一画布中绘制反映两种流失情况的客户各账号户龄占比量的堆叠柱状图,x 轴为客户的户龄,y 轴为占比量。
在这里插入图片描述

在这里插入图片描述

任务 3.4

新老客户各资产阶段的客户流失情况分析。
(1) 按照表 5 和表 6 对账号户龄和客户金融资产进行划分,并分别进行特征编码作为新的客户特征,其中客户状态存于“Status”列,资产阶段存于“AssetStage”列,编码结果保存到文件“result3.xlsx”中。在这里插入图片描述

def func3_4_1(x):
    if x>=0 and x<=3:
        return "新客户"
    elif x>3 and x<=6:
        return "稳定客户"
    elif x>6:
        return "老客户"
    else:
        return np.nan
def func3_4_2(x):
    if x>=0 and x<=50000:
        return "低资产"
    elif x>50000 and x<=90000:
        return "中下资产"
    elif x>90000 and x<= 120000:
        return "中上资产"
    elif x> 120000:
        return "高资产"
    else:
        return np.nan
	CustomerId	CreditScore	Gender	Age	Tenure	Balance	NumOfProducts	HasCrCard	IsActiveMember	EstimatedSalary	Exited	Status	AssetStage
0	15553251	713	1	52	0	185891.54	1	1	1	46369.57	1	0.0	3.0
1	15553256	619	1	41	8	0.00	3	1	1	79866.73	1	2.0	2.0
2	15553283	603	1	42	8	91611.12	1	0	0	144675.30	1	2.0	0.0
3	15553308	589	1	61	1	0.00	1	1	0	61108.56	1	0.0	2.0
4	15553387	687	1	39	2	0.00	3	0	0	188150.60	1	0.0	2.0
...	...	...	...	...	...	...	...	...	...	...	...	...	...
9193	15815628	711	1	37	8	113899.92	1	0	0	80215.20	0	2.0	0.0
9194	15815645	481	0	37	8	152303.66	2	1	1	175082.20	0	2.0	3.0
9195	15815656	541	1	39	9	100116.67	1	1	1	199808.10	1	2.0	0.0
9196	15815660	758	1	34	1	154139.45	1	1	1	60728.89	0	0.0	3.0
9197	15815690	614	1	40	3	113348.50	1	1	1	77789.01	0	0.0	0.0
9198 rows × 13 columns
le.categories_
[array(['新客户', '稳定客户', '老客户'], dtype=object),
 array(['中上资产', '中下资产', '低资产', '高资产'], dtype=object)]
data3_1.to_excel("result3.xlsx",index=None)

(2) 统计新、老客户在各资产阶段中流失的客户量,在同一画布中绘制热力图,热力图颜色的最大和最小取值设为 1300 和 100,并在报告中对结果进行必要分析。
在这里插入图片描述

任务 4 特征构建

基于长期数据提取影响客户流失的因素,构建与银行客户长期忠诚度相关的特征,将结果保存到文件“result4.xlsx”中。
(1) 根据表 7,构建新老客户活跃程度的特征,并将结果存于“IsActiveStatus”列
在这里插入图片描述

data4 = pd.read_excel("result3.xlsx")
data4
def func4_1(x):
    s = x.split(" ")
    if s[1] == "0":
        if s[0]=="0":
            return 0
        elif s[0]=="1":
            return 1
        elif s[0]=="2":
            return 2
        else:
            return np.nan
    elif s[1] == "1":
        if s[0]=="0":
            return 3
        elif s[0]=="1":
            return 4
        elif s[0]=="2":
            return 5
        else:
            return np.nan
    else:
        return np.nan
data4["IsActiveStatus"] = data4["Status"].apply(lambda x:str(x)+" ") + data4["IsActiveMember"].apply(str)
data4["IsActiveStatus"] = data4["IsActiveStatus"].apply(func4_1)

(2) 根据表 8,构建不同金融资产客户活跃程度的特征,并将结果存于“IsActiveAssetStage”列。
在这里插入图片描述

#['中上资产', '中下资产', '低资产', '高资产']
def func4_2(x):
    s = x.split(" ")
    if s[1] == "0":
        if s[0]=="2":
            return 0
        elif s[0]=="1":
            return 1
        elif s[0]=="0":
            return 2
        elif s[0]=="3":
            return 3
        else:
            return np.nan
    elif s[1] == "1":
        if s[0]=="2":
            return 6
        elif s[0]=="1":
            return 7
        elif s[0]=="0":
            return 8
        elif s[0]=="3":
            return 9
        else:
            return np.nan
    else:
        return np.nan
data4["IsActiveAssetStage"] = data4["AssetStage"].apply(lambda x:str(x)+" ") + data4["IsActiveMember"].apply(str)
data4["IsActiveAssetStage"] = data4["IsActiveAssetStage"].apply(func4_2)

(3) 根据表 9,构建不同金融资产信用卡持有状态的特征,并将结果存于“CrCardAssetStage”列。
在这里插入图片描述

def func4_3(x):
    s = x.split(" ")
    if s[1] == "0":
        if s[0]=="2":
            return 0
        elif s[0]=="1":
            return 2
        elif s[0]=="0":
            return 5
        elif s[0]=="3":
            return 5
        else:
            return np.nan
    elif s[1] == "1":
        if s[0]=="2":
            return 6
        elif s[0]=="1":
            return 7
        elif s[0]=="0":
            return 9
        elif s[0]=="3":
            return 9
        else:
            return np.nan
    else:
        return np.nan
data4["CrCardAssetStage"] = data4["AssetStage"].apply(lambda x:str(x)+" ") + data4["HasCrCard"].apply(str)
data4["CrCardAssetStage"] = data4["CrCardAssetStage"].apply(func4_3)
data4.to_excel("result4.xlsx",index=None)
data4
	CustomerId	CreditScore	Gender	Age	Tenure	Balance	NumOfProducts	HasCrCard	IsActiveMember	EstimatedSalary	Exited	Status	AssetStage	IsActiveStatus	IsActiveAssetStage	CrCardAssetStage
0	15553251	713	1	52	0	185891.54	1	1	1	46369.57	1	0	3	3	9	9
1	15553256	619	1	41	8	0.00	3	1	1	79866.73	1	2	2	5	6	6
2	15553283	603	1	42	8	91611.12	1	0	0	144675.30	1	2	0	2	2	5
3	15553308	589	1	61	1	0.00	1	1	0	61108.56	1	0	2	0	0	6
4	15553387	687	1	39	2	0.00	3	0	0	188150.60	1	0	2	0	0	0
...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...	...
9193	15815628	711	1	37	8	113899.92	1	0	0	80215.20	0	2	0	2	2	5
9194	15815645	481	0	37	8	152303.66	2	1	1	175082.20	0	2	3	5	9	9
9195	15815656	541	1	39	9	100116.67	1	1	1	199808.10	1	2	0	5	8	9
9196	15815660	758	1	34	1	154139.45	1	1	1	60728.89	0	0	3	3	9	9
9197	15815690	614	1	40	3	113348.50	1	1	1	77789.01	0	0	0	3	8	9
9198 rows × 16 columns

任务 5 银行客户长期忠诚度预测建模

# pip install --upgrade scikit-learn

长期数据存在“Exited”特征分布不均衡、各项数值分布跨度大等现象。体现为:未流失客户量是已流失客户量的 3 倍以上;客户信用资格最大数值达到 25万,而客户活动状态则为 0 和 1 等。考虑上述现象,对银行客户长期忠诚度进行预测。
(1) 选取适当的客户特征,建立客户长期忠诚度预测模型。客户特征可以从客户信用资格、性别、年龄、户龄、金融资产、客户购买产品数量、持有信用卡状态、活动状态和个人年收入等指标中直接选取,也可以参照任务 4 构建。在报告中给出特征选取的依据、建立预测模型的思路和过程。
(2) 使用混淆矩阵、F1 Score 等方法对预测模型进行评估,在报告中给出评估的方法和结果。
(3) 对“long-customer-test.csv”测试数据进行预测,将全部预测结果以表 10形式保存为文件“result5.xlsx”,其中 0 表示客户没有流失,1 表示客户流失。并将表 11 中的 5 个客户 ID 的预测结果在报告中列出。
在这里插入图片描述

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import seaborn as sns

# 读取数据
data5 = pd.read_excel("result4.xlsx")

# 选择特征和标签
x = data5.iloc[:,1:10]
y = data5["Exited"]

# 对数据进行无量纲化
scaler = MinMaxScaler()
x = scaler.fit_transform(x)

# 划分数据集与测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=422)

# 训练模型
model = SVC(C=10, kernel='poly', gamma=1.0, class_weight={1:3})
model.fit(x_train, y_train)

# 预测
y_pred = model.predict(x_test)

在这里插入图片描述

result5.xlsx 预测结果

```bash data_test_save ``` CustomerId Exited 0 15647311 1 1 15737452 1 2 15577657 0 3 15589475 1 4 15687946 1 ... ... ... 995 15732202 0 996 15735078 1 997 15707861 1 998 15594612 1 999 15806360 1 1000 rows × 2 columns
指定的 5 个客户 ID 的预测结果
    CustomerId  Exited
53     15730076       1
359    15674442       0
480    15792228       1
488    15719508       1
907    15579131       0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值