一、分析背景与目的
用户新增与用户流失每个时刻都可能发生,而激活老用户的成本是获得新用户的成本大致是5:1(甚至是更多),鉴于获客成本的考虑,更希望是把有价值的用户召回,把普通用户升级成活跃用户。
分析流失用户特征,深入了解流失客户;通过用户流失原因分析,建立流失用户画像和流失预测模型,为业务部门提供精细化运营,从而降低客户流失率。
二、数据理解
数据来源于kaggle官网:https://www.kaggle.com/blastchar/telco-customer-churn
大概有七千多条数据,21个特征指标;21个特征代表的含义如下:
字段名 | 字段描述 | 备注 |
---|---|---|
customerID | 客户ID | |
gender | 性别 | Female&Male |
SeniorCitizen | 是否是老年人 | 1表示是,0表示不是 |
Partner | 是否有伴侣 | Yes or No |
Dependents | 是否有家属 | Yes or No |
tenure | 使用产品时长 | 0-72个月 |
PhoneService | 是否开通电话服务业务 | Yes or No |
MultipleLines | 是否开通多线业务 | Yes、No or No phoneservice |
InternetService | 是否开通互联网服务 | No、DSL数字网络、fiber optic光纤网络 |
OnlineSecurity | 是否开通网络安全服务 | Yes、No or No internetserive |
OnlineBackup | 是否开通在线备份 | Yes、No or No internetserive |
DeviceProtection | 是否开通设备保护 | Yes、No or No internetserive |
TechSupport | 是否订购技术支持服务 | Yes、No or No internetserive |
StreamingTV | 是否订购网络电视 | Yes、No or No internetserive |
StreamingMovies | 是否订购网络电影 | Yes、No or No internetserive |
Contract | 签订合同方式 | 按月、一年、两年 |
PaperlessBilling | 是否开通电子账单 | Yes or No |
PaymentMethod | 客户端支付方式 | bank transfer, credit card, electronic check,mailed check |
MonthlyCharges | 月费用 | |
TotalCharges | 总费用 | |
Churn | 是否流失 | Yes or No |
分析思路:
三、数据清洗
#导入相关的库
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
plt.rcParams['axes.unicode_minus']=False # 正常显示负号
plt.style.use('ggplot')
#忽略警告信息
import warnings
warnings.filterwarnings("ignore")
1、读取并查看数据
data=pd.read_csv('./churn.csv')
data.head()
data.info()
一共有七千多条样本,21个特征,没有缺失值,数据完整
2、数据类型转换
#把totalcharges总费用列转化为float类型
#data['TotalCharges'] = data['TotalCharges'].astype(float)#执行错误,有数据为空格;需将删除后再转换
data[data['TotalCharges']==' ']
#TotalCharges空格数据较少(11个),将其删除
data=data[~data['TotalCharges'].isin([' '])]
data['TotalCharges'] = data['TotalCharges'].astype(float)
data.describe()
可以看到电信用户大部分为年轻人,人均时长在32个月左右,人均月消费64.8美元,人均总消费在2283美元左右;消费时间跟消费金额差异都是比较大。
四、数据分析—流失用户画像分析
1、总流失率
plt.figure(figsize=(12,5))
plt.pie(data['Churn'].value_counts().values,autopct='%1.2f%%',labels=data['Churn'].value_counts().index,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('流失人数占比(Yes/No)',fontsize=18)
row_labels = ['No', 'Yes']
col_labels=['人数','人数']
table_vals = [[5163],[1869]]#data['Churn'].value_counts().values
row_colors = ['red','green']
my_table = plt.table(cellText=table_vals, colWidths=[0.1]*2,colLabels=col_labels,colColours=row_colors,
rowLabels=row_labels, rowColours=row_colors, loc='lower right')
my_table.set_fontsize(15)
plt.show()
2、流失用户画像
(1)、用户基本信息
1)、年龄(老年人、非老年人)
df_age=data.groupby('Churn')['SeniorCitizen'].value_counts()
df_age
plt.figure(figsize=(10,5))
plt.subplot(211)
vals1 = [4497,666] #df_age.values
labels =['非老年人','老年人'] #df_age.index
plt.pie(vals1,autopct='%1.2f%%',labels=labels,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('非流失用户中老年人的占比',fontsize=18)
plt.subplot(212)
vals2 = [1393,476]
labels =['非老年人','老年人']
plt.pie(vals2,autopct='%1.2f%%',labels=labels,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('流失用户中老年人的占比',fontsize=18)
row_labels = labels
col_labels=['非流失用户数','流失用户数']
table_vals = [[4497,1393],[666,476]]
row_colors = ['red','green']
my_table = plt.table(cellText=table_vals, colWidths=[0.15]*2,colLabels=col_labels,colColours=row_colors,
rowLabels=row_labels, rowColours=row_colors, loc='lower right')
my_table.set_fontsize(15)
plt.show()
老年人用户少,但是老年人流失率高。
2)、伴侣
df_partner=data.groupby('Churn')['Partner'].value_counts()
df_partner
plt.figure(figsize=(10,5))
plt.subplot(211)
vals1 = [2724,2439]
labels =['有','无']
plt.pie(vals1,autopct='%1.2f%%',labels=labels,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('非流失用户伴侣(有/无)情况',fontsize=18)
plt.subplot(212)
vals2 = [669,1200]
labels =['有','无']
plt.pie(vals2,autopct='%1.2f%%',labels=labels,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('流失用户伴侣(有/无)情况',fontsize=18)
row_labels = labels
col_labels=['非流失用户数','流失用户数']
table_vals = [[2724,669],[2439,1200]]
row_colors = ['red','green']
my_table = plt.table(cellText=table_vals, colWidths=[0.15]*2,colLabels=col_labels,colColours=row_colors,
rowLabels=row_labels, rowColours=row_colors, loc='lower right')
my_table.set_fontsize(15)
plt.show()
无伴侣用户更容易流失。
3)、性别
df_gender=data.groupby('Churn')['gender'].value_counts()
df_gender
plt.figure(figsize=(10,5))
plt.subplot(211)
vals1 = [2619,2544]
labels =['男','女']
plt.pie(vals1,autopct='%1.2f%%',labels=labels,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('非流失用户性别')
plt.subplot(212)
vals2 = [930,939]
labels =['男','女']
plt.pie(vals2,autopct='%1.2f%%',labels=labels,explode=(0.05,0),colors=['red','green'],textprops={
'fontsize':15})
plt.legend()
plt.axis('equal')
plt.title('流失用户性别情况',fontsize=15)
row_labels = labels
col_labels=['非流失用户数','流失用户数']
table_vals = [[2619,930],[2544,939]]
row_colors = ['red','green']
my_table = plt.table(cellText=table_vals, colWidths=[0.15]*2,colLabels=col_labels,colColours=row_colors,
rowLabels=row_labels, rowColours=row_colors, loc='lower right')
my_table.set_fontsize(15)
plt.show()
性别跟流失与否几乎没差异。
4)、家属
df_dependents=data.groupby('Churn')['Dependents'].value_counts()
df_dependents
plt.figure(figsize=(10,5))
plt.subplot(211)
vals1 = [3390,1773]
labels =['无','有']
plt.pie(vals1,autopct='%1.2f%%',labels=labels,explode=(0.05