运营商客户流失率分析

1.数据集说明

每一行代表一个客户,每一列包含列元数据中描述的客户属性。原始数据包含7043行(客户)和21列(特性)。

字段字段字段说明
customerID:用户ID身份标识
gender性别(male,female )
SeniorCitizen是否老年人(0, 1 )
Partner是否有伴侣(No, Yes )
Dependents是否有抚养人(No, Yes )
tenure客户入网时长(月)(连续值 0-72 )
PhoneService是否有电话服务(Yes, No)
MultipleLines是否有多线服务(Yes, No, No phone service)
InternetService客户互联网服务提供商(No, DSL数字网络,fiber optic光纤网络 )
OnlineSecurity是否有在线安全(Yes, No, No internet service)
OnlineBackup是否在线备份(Yes, No, No internet service)
DeviceProtection设备保护策略(Yes, No, No internet service)
TechSupport技术支持(Yes, No, No internet service)
StreamingTV在线电视(Yes, No, No internet service)
StreamingMovies在线电影(Yes, No, No internet service)
Contract合同(month-to-month, two year, One year)
PaperlessBilling无纸账单(Yes, No)
PaymentMethod支付方式(Electronic check, Mailed check, Bank transfer (automatic), Credit card (automatic))
MonthlyCharges每月服务费(连续值)
TotalCharges总话费(连续值)
Churn流失标签(No, Yes)

2.分析思路

寻找与流失率有关的特征,进一步分析这些特征如何影响流失率,刻画高流失率用户画像,对高流失率用户提供建议。

3.数据预处理

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from datetime import datetime

%matplotlib inline
plt.style.use('ggplot')
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
df = pd.read_csv('电信运营商客户数据集.csv')
df.head()
customerIDgenderSeniorCitizenPartnerDependentstenurePhoneServiceMultipleLinesInternetServiceOnlineSecurity...DeviceProtectionTechSupportStreamingTVStreamingMoviesContractPaperlessBillingPaymentMethodMonthlyChargesTotalChargesChurn
07590-VHVEGFemale0YesNo1NoNo phone serviceDSLNo...NoNoNoNoMonth-to-monthYesElectronic check29.8529.85No
15575-GNVDEMale0NoNo34YesNoDSLYes...YesNoNoNoOne yearNoMailed check56.951889.5No
23668-QPYBKMale0NoNo2YesNoDSLYes...NoNoNoNoMonth-to-monthYesMailed check53.85108.15Yes
37795-CFOCWMale0NoNo45NoNo phone serviceDSLYes...YesYesNoNoOne yearNoBank transfer (automatic)42.301840.75No
49237-HQITUFemale0NoNo2YesNoFiber opticNo...NoNoNoNoMonth-to-monthYesElectronic check70.70151.65Yes

5 rows × 21 columns

#查看数据信息
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 21 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   customerID        7043 non-null   object 
 1   gender            7043 non-null   object 
 2   SeniorCitizen     7043 non-null   int64  
 3   Partner           7043 non-null   object 
 4   Dependents        7043 non-null   object 
 5   tenure            7043 non-null   int64  
 6   PhoneService      7043 non-null   object 
 7   MultipleLines     7043 non-null   object 
 8   InternetService   7043 non-null   object 
 9   OnlineSecurity    7043 non-null   object 
 10  OnlineBackup      7043 non-null   object 
 11  DeviceProtection  7043 non-null   object 
 12  TechSupport       7043 non-null   object 
 13  StreamingTV       7043 non-null   object 
 14  StreamingMovies   7043 non-null   object 
 15  Contract          7043 non-null   object 
 16  PaperlessBilling  7043 non-null   object 
 17  PaymentMethod     7043 non-null   object 
 18  MonthlyCharges    7043 non-null   float64
 19  TotalCharges      7043 non-null   object 
 20  Churn             7043 non-null   object 
dtypes: float64(1), int64(2), object(18)
memory usage: 1.1+ MB

没有数据缺失。

#是否有重复数据
sum(df.duplicated())
0
sum(df.customerID.duplicated())
0

一共有7043名用户的数据。

#将TotalCharges(总消费额)转换为浮点型,错误充为nan值
df['TotalCharges'] = pd.to_numeric( df['TotalCharges'],errors=  'coerce' )
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 21 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   customerID        7043 non-null   object 
 1   gender            7043 non-null   object 
 2   SeniorCitizen     7043 non-null   int64  
 3   Partner           7043 non-null   object 
 4   Dependents        7043 non-null   object 
 5   tenure            7043 non-null   int64  
 6   PhoneService      7043 non-null   object 
 7   MultipleLines     7043 non-null   object 
 8   InternetService   7043 non-null   object 
 9   OnlineSecurity    7043 non-null   object 
 10  OnlineBackup      7043 non-null   object 
 11  DeviceProtection  7043 non-null   object 
 12  TechSupport       7043 non-null   object 
 13  StreamingTV       7043 non-null   object 
 14  StreamingMovies   7043 non-null   object 
 15  Contract          7043 non-null   object 
 16  PaperlessBilling  7043 non-null   object 
 17  PaymentMethod     7043 non-null   object 
 18  MonthlyCharges    7043 non-null   float64
 19  TotalCharges      7032 non-null   float64
 20  Churn             7043 non-null   object 
dtypes: float64(2), int64(2), object(17)
memory usage: 1.1+ MB

TotalCharges(总消费额)有缺失值。

df[df.TotalCharges.isin([np.NaN])]
customerIDgenderSeniorCitizenPartnerDependentstenurePhoneServiceMultipleLinesInternetServiceOnlineSecurity...DeviceProtectionTechSupportStreamingTVStreamingMoviesContractPaperlessBillingPaymentMethodMonthlyChargesTotalChargesChurn
4884472-LVYGIFemale0YesYes0NoNo phone serviceDSLYes...YesYesYesNoTwo yearYesBank transfer (automatic)52.55NaNNo
7533115-CZMZDMale0NoYes0YesNoNoNo internet service...No internet serviceNo internet serviceNo internet serviceNo internet serviceTwo yearNoMailed check20.25NaNNo
9365709-LVOEQFemale0YesYes0YesNoDSLYes...YesNoYesYesTwo yearNoMailed check80.85NaNNo
10824367-NUYAOMale0YesYes0YesYesNoNo internet service...No internet serviceNo internet serviceNo internet serviceNo internet serviceTwo yearNoMailed check25.75NaNNo
13401371-DWPAZFemale0YesYes0NoNo phone serviceDSLYes...YesYesYesNoTwo yearNoCredit card (automatic)56.05NaNNo
33317644-OMVMYMale0YesYes0YesNoNoNo internet service...No internet serviceNo internet serviceNo internet serviceNo internet serviceTwo yearNoMailed check19.85NaNNo
38263213-VVOLGMale0YesYes0YesYesNoNo internet service...No internet serviceNo internet serviceNo internet serviceNo internet serviceTwo yearNoMailed check25.35NaNNo
43802520-SGTTAFemale0YesYes0YesNoNoNo internet service...No internet serviceNo internet serviceNo internet serviceNo internet serviceTwo yearNoMailed check20.00NaNNo
52182923-ARZLGMale0YesYes0YesNoNoNo internet service...No internet serviceNo internet serviceNo internet serviceNo internet serviceOne yearYesMailed check19.70NaNNo
66704075-WKNIUFemale0YesYes0YesYesDSLNo...YesYesYesNoTwo yearNoMailed check73.35NaNNo
67542775-SEFEEMale0NoYes0YesYesDSLYes...NoYesNoNoTwo yearYesBank transfer (automatic)61.90NaNNo

11 rows × 21 columns

总消费额缺失的用户,入网时长为0,但显示没有流失,可能是数据记录错误,也可能是免费合约。没有分析意义,应该剔除。

df.dropna(inplace = True)
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 7032 entries, 0 to 7042
Data columns (total 21 columns):
 #   Column            Non-Null Count  Dtype  
---  ------            --------------  -----  
 0   customerID        7032 non-null   object 
 1   gender            7032 non-null   object 
 2   SeniorCitizen     7032 non-null   int64  
 3   Partner           7032 non-null   object 
 4   Dependents        7032 non-null   object 
 5   tenure            7032 non-null   int64  
 6   PhoneService      7032 non-null   object 
 7   MultipleLines     7032 non-null   object 
 8   InternetService   7032 non-null   object 
 9   OnlineSecurity    7032 non-null   object 
 10  OnlineBackup      7032 non-null   object 
 11  DeviceProtection  7032 non-null   object 
 12  TechSupport       7032 non-null   object 
 13  StreamingTV       7032 non-null   object 
 14  StreamingMovies   7032 non-null   object 
 15  Contract          7032 non-null   object 
 16  PaperlessBilling  7032 non-null   object 
 17  PaymentMethod     7032 non-null   object 
 18  MonthlyCharges    7032 non-null   float64
 19  TotalCharges      7032 non-null   float64
 20  Churn             7032 non-null   object 
dtypes: float64(2), int64(2), object(17)
memory usage: 1.2+ MB
df.describe()
SeniorCitizentenureMonthlyChargesTotalCharges
count7032.0000007032.0000007032.0000007032.000000
mean0.16240032.42178664.7982082283.300441
std0.36884424.54526030.0859742266.771362
min0.0000001.00000018.25000018.800000
25%0.0000009.00000035.587500401.450000
50%0.00000029.00000070.3500001397.475000
75%0.00000055.00000089.8625003794.737500
max1.00000072.000000118.7500008684.800000

目前还有7032个客户信息。

3.数据分析及可视化

3.1.总体流失率分析
plt.figure(figsize = (12,6))
plt.subplot(121)
plt.pie(df['Churn'].value_counts(),labels=df['Churn'].value_counts().index,autopct='%1.2f%%',explode=(0.1,0))
plt.title('用户流失和非流失占比')

plt.subplot(122)
x, y = df['Churn'].value_counts().index, df['Churn'].value_counts().values
plt.bar(x, y, width=0.35)
plt.title('用户流失和非流失人数')
for a,b in zip(x,y):
    plt.text(a, b-0.3,'%.3f'%b, ha = 'center',va = 'bottom',fontsize=15)

在这里插入图片描述
流失人数为1869人,占比26.58%。

3.2.用户属性分析

性别、是否老年人、是否有伴侣、是否有抚养人、入网时长与流失率的关系

df.iloc[:,1:5].columns
Index(['gender', 'SeniorCitizen', 'Partner', 'Dependents'], dtype='object')
def churn_rate(data,column):  #流失率函数
    
    df1 = data[data[column] == data[column].unique()[0]]
    df2 = data[data[column]  == data[column].unique()[1]]
    df_Churn1 = len(df1.query('Churn == "Yes"'))/len(df1)
    df_Churn2 = len(df2.query('Churn == "Yes"'))/len(df2)
    p = plt.bar( [data[column].unique()[0],data[column].unique()[1]],[df_Churn1,df_Churn2])
    plt.ylabel('流失率')
    return plt

plt.figure(figsize = (12,8))
plt.subplot(221)
churn_rate(df,'gender')
plt.title('性别与流失率')

plt.subplot(222)
churn_rate(df,'SeniorCitizen')
plt.title('年龄与流失率')
plt.xticks([0,1],['非老年人','老年人'])

plt.subplot(223)
churn_rate(df,'Partner')
plt.title('伴侣与流失率')
plt.xticks([0,1],['有伴侣','无伴侣'])

plt.subplot(224)
churn_rate(df,'Dependents')
plt.title('抚养人与流失率')
plt.xticks([0,1],['无抚养人','有抚养人'])
([<matplotlib.axis.XTick at 0x1ae1c0b7148>,
  <matplotlib.axis.XTick at 0x1ae1c0ac248>],
 <a list of 2 Text xticklabel objects>)

在这里插入图片描述

性别与流失率无关。
老年用户比非老年用户流失率高,流失率分别为42%,24%。
无伴侣用户比有伴侣用户流失率高,流失率分别为34%,20%。
无抚养人用户比有抚养人用户的流失率高,流失率分别为32%,16%。

#入网时长与流失率
plt.figure(figsize = (12,6))
df.query('Churn == "Yes"').tenure.plot(kind = 'kde')
plt.title('不同入网时长的流失密度图')
plt.xlabel('入网时长')
plt.ylabel('密度')
plt.axvline(3,color = 'b')
plt.axvline(6,color = 'b')
plt.axvline(16,color = 'b')
plt.text(1,0.01,3,fontsize=15)
plt.text(7,0.01,6,fontsize=15)
plt.text(17,0.01,16,fontsize=15)

在这里插入图片描述

入网6个月内的用户流失概率最高,其中入网三个月的用户流失概率达到峰值。总体来看,入网时间越长,流失概率越小。
入网第3个月是用户流失的高发期,在前15个月内,提高用户入网时长,对于降低流失率作用显著。建议通过一些策略将用户入网时间提高到3-6个月以后,比如三个月优惠期、入网满三个月发放优惠或奖励等。

3.3.服务属性分析

是否有电话服务(Yes, No)
是否有多线服务(Yes, No, No phone service)
客户互联网服务提供商 (No, DSL数字网络,fiber optic光纤网络)
是否有在线安全(Yes, No, No internet service)
是否在线备份(Yes, No, No internet service)
设备保护策略(Yes, No, No internet service)
技术支持(Yes, No, No internet service)
在线电视(Yes, No, No internet service)
在线电影(Yes, No, No internet service)

df.iloc[:,6:15].columns
Index(['PhoneService', 'MultipleLines', 'InternetService', 'OnlineSecurity',
       'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV',
       'StreamingMovies'],
      dtype='object')
#互联网服务提供商与流失率
def service_churn_rate(data,column):
    service = pd.DataFrame(data.groupby([column,'Churn']).customerID.count())
    service_sum = service.groupby(column).customerID.transform(sum)   
    service_churn_rate1 = (service['customerID']/service_sum).xs('Yes',level = 1)
   
    return service_churn_rate1

plt.figure(figsize = (8,4))
service_churn_rate(df,'InternetService').plot(kind = 'bar')
plt.title('互联网服务提供商与流失率')
plt.xticks([0,1,2],['No','DSL数字网络','光纤网络'])

在这里插入图片描述
数字网络和光纤网络的用户流失率分别为0.19、0.42,没有互联网服务的用户流失率为0.07。
可以看出没有互联网服务的用户,其流失率远低于有互联网服务的用户;数字网络DSL的流失率高于光纤网络。

column = list(df.iloc[:,6:15].columns)
column.remove('InternetService')
other_service_churn = pd.Series()
for i in column:
    a = service_churn_rate(df,i)
    other_service_churn = pd.concat([other_service_churn,a],axis =1)

other_service_churn = other_service_churn.drop(0,axis = 1)
other_service_churn.columns = ['电话服务','多线服务','在线安全','在线备份','设备保护策略','技术支持','在线电视','在线电影']
other_service_churn

C:\ProgramData\Anaconda3\lib\site-packages\ipykernel_launcher.py:3: DeprecationWarning: The default dtype for empty Series will be 'object' instead of 'float64' in a future version. Specify a dtype explicitly to silence this warning.
  This is separate from the ipykernel package so we can avoid doing imports until
电话服务多线服务在线安全在线备份设备保护策略技术支持在线电视在线电影
No0.2500000.2508120.4177870.3994170.3914030.4164750.3353510.337289
Yes0.2674750.2864850.1464020.2156700.2253930.1519610.3011470.299524
No phone serviceNaN0.250000NaNNaNNaNNaNNaNNaN
No internet serviceNaNNaN0.0743420.0743420.0743420.0743420.0743420.074342
#其他服务与流失率 =
plt.rcParams['xtick.labelsize']=18
plt.rcParams['axes.labelsize'] = 25
plt.rcParams['axes.titlesize'] = 20

other_service_churn.T.plot(kind = 'bar',figsize = (18,8),)
plt.title('其他服务与流失率')
plt.ylabel('流失率')

在这里插入图片描述

电话服务、多线服务、在线电视、在线电影与流失率关系不大。
没有互联网服务的用户流失率在0.07左右,远低于有互联网服务的用户。
在线安全、在线备份、设备保护策略、在线技术支持与流失率关系较大。在这四个服务中,有服务的用户流失低于没有服务的用户,没有这四个服务的用户流失率均在0.4左右,其中开通在线安全和技术支持的用户流失率最低。
虽然没有互联网服务的用户流失率低,但由于开通服务能得到更多收益,应该使用户在开通服务的前提下减少流失率。

3.4.合同属性分析

合同期 (month-to-month, two year, One year)
无纸账单(Yes, No)
支付方式(Electronic check电子支付, Mailed check邮件支付, Bank transfer (automatic)银行自动转账, Credit card (automatic)信用卡自动支付)
每月服务费
总消费额

plt.rcParams['xtick.labelsize']=15
plt.rcParams['axes.labelsize'] = 12
plt.rcParams['axes.titlesize'] = 16
plt.figure(figsize = (18,14))

plt.subplot(221)
service_churn_rate(df,'Contract').plot(kind = 'bar')
plt.title('合同期与流失率')
plt.xticks([0,1,2],['每月到期续签','一年','两年'])

plt.subplot(222)
service_churn_rate(df,'PaperlessBilling').plot(kind = 'bar')
plt.title('有纸账单与流失率')
plt.xticks([0,1],['有纸账单','无纸账单'])

plt.subplot(212)
service_churn_rate(df,'PaymentMethod').plot(kind = 'bar')
plt.title('支付方式与流失率')
plt.xticks([0,1,2,3],['银行自动转账','信用卡自动支付','电子支付','邮件支付'])

在这里插入图片描述
合同期、有纸账单、支付方式均对流失率有影响。
合同期越短,流失率越高。每月到期续签的流失率达到0.4,远高于一年期和两年期的用户。
电子账单的流失率(0.33)高于有纸账单(0.17)。
电子支付的流失率高于其他支付方式。电子支付的流失率是0.48,其他支付方式的流失率在0.15-0.2之间。

#支付费用与流失率
plt.figure(figsize = (12,12))
plt.subplot(221)
df.query('Churn == "Yes"').MonthlyCharges.plot(kind = 'kde')
plt.title('不同月服务费的流失密度图')
plt.xlabel('每月服务费')
plt.ylabel('密度')
plt.axvline(80,color = 'b')
plt.axvline(60,color = 'b')
plt.axvline(118,color = 'b')
plt.text(82,0.01,80,fontsize=15)
plt.text(62,0.01,60,fontsize=15)
plt.text(120,0.01,118,fontsize=15)
plt.subplot(222)
df.query('MonthlyCharges > 100').query('Churn == "Yes"').MonthlyCharges.plot(kind = 'kde')
plt.title('月费>100的流失密度图')

plt.subplot(212)
df.query('Churn == "Yes"').TotalCharges.plot(kind = 'kde')
plt.title('不同总消费额的流失密度图')
plt.xlabel('总消费额')
plt.ylabel('密度')
plt.axvline(250,color = 'b')
plt.text(270,0.0001,250,fontsize=15)

在这里插入图片描述

月费在18-118之间。月费70-100的用户流失概率较高,60以下的用户流失概率较低,80达到峰值。对于月费小于80的用户,提高月费会增加流失概率,尤其是月费在60-80的用户;对于月费大于80的用户,提高月费会降低流失概率,尤其是月费大于100的用户。
总消费额在18-8700之间。总消费额为250的用户流失概率最高,大于或小于250的流失概率迅速减小,总消费额在2000以上的流失概率较小。一般来说,总消费越高,表明留存时间越长,流失概率也就越小。

4.高流失率用户画像

在这里插入图片描述

5.结论和建议

  1. 老年人、无伴侣、无抚养人的用户流失率更高,建议针对这部分用户的特点,制定专属套餐,推荐合理的套餐组合。

  2. 总体来看,入网时间越长,流失概率越小。入网第3个月是用户流失的高发期,在前15个月内,提高用户入网时长,对于降低流失率作用显著。建议通过一些策略将用户入网时间提高到3-6个月以后,比如三个月优惠期、入网满三个月发放优惠或奖励等。

  3. 数字网络DSL的流失率高于光纤网络。建议对数字网络用户情况和服务作进一步分析,以确定具体原因。

  4. 没有互联网服务的用户流失率在0.07左右,远低于有互联网服务的用户。虽然没有互联网服务的用户流失率低,但由于开通服务能得到更多收益,应该在用户开通服务的前提下,减少流失率。

  5. 在线安全、在线备份、设备保护策略、在线技术支持与流失率关系较大。在这四个服务中,有服务的用户流失低于没有服务的用户,其中开通在线安全和技术支持的用户流失率最低。对于有互联网服务的用户,建议让其开通在线安全或技术支持服务,可降低60%左右的流失概率。

  6. 合同期越短,流失率越高;电子账单的流失率高于有纸账单;电子支付的流失率高于其他支付方式。延长用户合同期有利于降低流失率,建议通过优惠吸引用户签订一年期、两年期,比如前几个月减免、赠送其他服务等。

  7. 月费70-100的用户流失概率较高,60以下的用户流失概率较低,80达到峰值。对于月费小于80的用户,提高月费会增加流失概率,尤其是60-80的用户应该谨慎提高其月费;对于月费大于80的用户,提高月费会降低流失概率,尤其是大于100的用户增加其月费,或增加服务,可以降低流失概率。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值