目录
1.项目背景
激烈的市场竞争下,客户一旦发生流失,就很难在成功挽回,特别是现在的人口红利已经见顶,获取一个新客户的成本远高于维系一个老客户,而老客户的流失意味着收益的流失和市场占有率的下降,对于企业的生存发展来说是个危险的信号。然而客户的流失,是无法避免的,但是我们可以通过有效的手段来减少客户的流失,提高客户的留存率。
目的:
通过数据分析找出customerID影响客户流失的因素,并提出针对性的决策建议,为电信运营商提出优化业务决策,减少客户流失的决策建议。
思路:
首先通过合理的纬度拆解方法对用户数据进行拆解,利用数据探索和可视化等方法研究对各个维度的字段与客户流失的相关性,找出影响客户流失的因素;筛选出这些数据进行特征工程的处理,建立决策树模型对特征重要性进行排序,结合以上分析结果,从业务角度为电信公司增强客户留存率、减少客户流失提出具体的决策建议。
2.数据探索(EDA)
2.1数据集信息![](https://img-blog.csdnimg.cn/01b645b6b091450ea2ffc5a864e6d836.png)
部分字段含义解释
customerID:顾客ID
gender: 性别
SeniorCitizen: 是否为老人
Partner:是否有伴侣
Dependents:是否有孩子
tenure:上网时长(月)
PhoneService:是否有电话服务
MultipleLines:是否使用
InternetService:是否使用网络服务
Contract:合同期限
PaperlessBilling:是否开通电子支付
PaymentMethod:账单类型
MonthlyCharges:月消费
TotalCharges:总消费
Churn:流失情况
总共有21个字段。
接下来通过info()了解数据类型,查看数据类型是否合理,以及nan值的情况。
通过数据类型检查发现,TotalCharges总消费的数据类型应该为float,而不是object,需要修改。
user_info['TotalCharges'] = user_info['TotalCharges'].replace(' ', np.nan, regex=True)
user_info['TotalCharges'] = pd.to_numeric(user_info['TotalCharges'])
修改完毕。
接着通过describe 查看数据集的统计量,主要了解数据的大概范围以及每个特征的异常值判断。
用户最高上网市场是72个月,最高月消费118.75,最高总消费是8684.8。这里没有发现什么异常值。下一步看看看异常值和缺失值的情况。
2.2 异常值分析
通过上一步,我们并没有发现异常值,但并不代表没有,为了进一步确认,我们使用箱型图查看tenure、MonthlyCharges、TotalCharges是否存在异常。
可以看到tenure、MonthlyCharges、TotalCharges并不存在异常值。
2.3 缺失值分析
查看缺失值情况:
TotalCharges存在11条缺失值,量比较小,这选择直接删除
user_info.dropna(inplace=True)
print(user_info.isnull().sum())
已经成功删除。
查看数据纬度
一共有7032行。
查看流失情况
查看流失率
流失率为1869/7032=26.5%,这个流失率很夸张了,但是电信行业的流失率多少算正常没有找到准确的资料。
3.数据预览
我们把用户数据根据人-货-场三个纬度进行拆分:
3.1 人
3.1.1 用户属性
3.1.1.1 性别
sns.countplot(x='gender',hue='Churn',data=user_info)
plt.xlabel('性别')
plt.ylabel('数量')
plt.title('性别与客户流失情况图')
plt.show()
可以看到男性与女性用户的人数基本一致,流失率也基本相同,故判断性别不会影响客户的流失。
3.1.1.2 是否老年人
sns.countplot(x='SeniorCitizen',hue='Churn',data=user_info,order=[0,1],hue_order=['Yes','No'])
plt.xlabel('是否为老年人')
plt.ylabel('数量')
plt.title('是否为老年人与流失情况图')
plt.show()
0-不是老年人,1-是老年人,老年人的人数为1142,年轻人为5890,可以看到老年人的流失率远高于不是老年人的流失率。猜测可能地原因有:1、年龄大了,对使用电话和网络不感兴趣;2、上网等各种功能比较繁琐,老人无法完全理解和使用。3、可能老年人已经离世了。对于第一点猜测,我通过拉取老年人中开通电话和网络的数据来验证,结果表明,老年人中85%以上的人都开通了网络服务,但是开通了网络服务的那部分的老年人流失情况比没有开通网络服务的老年人更加严重,是否开通电话服务对流失没有影响,猜想是不是光纤网络问题导致了老人年的流失。从电话服务上看,是否开通了这项服务,老年人的流失情况都很严重,是不是老年人的实际需求并未得到满足。
3.1.1.3 是否有伴侣
ns.countplot(x='Partner',data=user_info, hue = 'Churn')
plt.xlabel('是否有伴侣')
plt.ylabel('数量')
plt.title('是否有伴侣与流失情况图')
plt.show()
从图表上观察来说,是否有伴侣对客户流失地影响不大, 实际情况也如此。
3.1.1.4 是否有小孩
sns.countplot(x='Dependents',data=user_info, hue = 'Churn',hue_order=['Yes','No'])
plt.xlabel('是否有小孩')
plt.ylabel('数量')
plt.title('是否有小孩与流失情况图')
plt.show()
可以发现是否有小孩对客户流失地影响不大, 实际情况也如此。
小结:
从用户属性这个层面上看,对流失有影响的因素为是否是老人,并且可以定位到开通光纤网络后,老人的流失反而更为严重,需要进一步分析。
3.1.2 用户行为
3.1.2.1 合同期限
sns.countplot(x='Contract',hue='Churn',data=user_info,hue_order=['Yes','No'],order=['Month-to-month','One year','Two year'])
plt.title('合同期限与流失情况图')
plt.xlabel('合同期限')
plt.ylabel('数量')
plt.show()
可以看到,合同签约的越长,用户流失的概率就越低,这告诉我们在签订合同的时候,可以提高与客户签订的合同期限。
3.1.2.2 支付方式
sns.countplot(x='PaperlessBilling',hue='Churn',data=user_info,hue_order=['Yes','No'],dodge=True)
plt.title('是否开通电子账单与流失情况图')
plt.xlabel('是否开通电子账单')
plt.ylabel('数量')
plt.show()
使用电子支付的人员流失明显比其他支付方式更为严重,是不是电子支付在设计或者功能上存在漏洞。
3.1.2.3 账单类型
sns.countplot(x='PaymentMethod',hue='Churn',data=user_info,hue_order=['Yes','No'],dodge=True,order=['Electronic check','Mailed check','Bank transfer (automatic)','Credit card (automatic)'])
plt.title('支付方式与流失情况图')
plt.xlabel('支付方式')
plt.ylabel('数量')
plt.show()
电子账单的流失率高于其他的账单类型,与上面是否开通电子支付的结果一致,基本可以确认电子账单对客户的流失造成了影响。
3.1.2.4 月消费
我们使用核密度曲线来观察月消费和流失之间的关系。
def kdeplot(feature,xlabel):
plt.figure(figsize=(9, 4))
plt.title("KDE for {0}".format(feature))
ax0 = sns.kdeplot(user_info[user_info['Churn'] == 'No'][feature].dropna(), color= 'navy', label= 'Churn: No', shade='True')
ax1 = sns.kdeplot(user_info[user_info['Churn'] == 'Yes'][feature].dropna(), color= 'orange', label= 'Churn: Yes',shade='True')
plt.xlabel(xlabel)
#设置字体大小
plt.rcParams.update({'font.size': 20})
plt.legend(fontsize=10)
kdeplot('MonthlyCharges','MonthlyCharges')
plt.show()
当月消费价格超过60以上,用户的流失率就会增加,因为偶尔一个月的话费超支很是让人恼火,因此换一家服务商很常见。
3.1.2.5 总消费
可以看到,用户花的钱越多,留存率就越高,精细化的运营,才是留存最有效的办法。
3.1.2.6 在网时长(tenure)
def kdeplot(feature,xlabel):
plt.figure(figsize=(9, 4))
plt.title("KDE for {0}".format(feature))
ax0 = sns.kdeplot(user_info[user_info['Churn'] == 'No'][feature].dropna(), color= 'navy', label= 'Churn: No', shade='True')
ax1 = sns.kdeplot(user_info[user_info['Churn'] == 'Yes'][feature].dropna(), color= 'orange', label= 'Churn: Yes',shade='True')
plt.xlabel(xlabel)
#设置字体大小
plt.rcParams.update({'font.size': 20})
plt.legend(fontsize=10)
kdeplot('tenure','tenure')
plt.show()
结果表明在网时长达到三个月后,客户流失率小于在网率,据此,我们可以在签订合同的时候,让用户尽量签三个月以上的合同,以此来提高用户地留存率。
3.2 货
3.2.1 电话服务
3.2.1.1 是否支持电话服务
每个公司都有电话服务,这个应该不是影响流失的因素,图像上也没有特别明显的表现。
3.2.1.2 是否支持多线程
可以看到是否支持多线程与流失没有太大相关性,因为这个功能本身就很少的人在使用,即使出现了bug也不会影响用户的体验。
3.2.2 网络服务
3.2.2.1 是否支持上网
可以看到开通了网络服务的客户流失率比未开通网络服务的客户流失率还要严重,特别是光纤网络,流失率明显高于另外两组,是不是光纤网络的使用上存在bug或者是其他原因,需要详细调查。
3.2.2.2 在线安全
上网安全一直以来都是人们注意的焦点,当自己个人隐私在网上泄露之后,随之而来的是各种奇怪的推送,让用户苦恼不已,数据也证明了,当上网安全得不到保障时,用户就会流失。
3.2.2.3 在线备份
在线备份是一项很有用的功能,有时候忘记保存而退出网址,通过在线备份可以重新进入,节约了我们的时间。在线备份也是影响流失的因素。
3.2.2.4 设备保护
设备保护与网络安全都是与用户的上完安全相关,这两个方面功能的缺失,会导致用户的流失。
3.2.2.5 技术支持
技术支持也是用户流失的重要影响因素。
3.2.2.6 是否支持流媒体电视
是否有流媒体电视这个功能对流失没有影响。
3.2.2.7 是否支持流媒体电影
这个对客户流失也没有影响。
4. 特征工程
4.1 特征选择
根据上述分析,与客户流失有关的因素有:是否为老年人、合同期限、在网时长、支付方式、月消费、是否使用网络服务,是否采用网络安全、网络备份、设备保护、技术支持。重新定义数据集user_df.
user_df=user_info.loc[:,('SeniorCitizen','Contract','tenure','PaymentMethod','MonthlyCharges','InternetService','OnlineSecurity','OnlineBackup','DeviceProtection','TechSupport','Churn')]
4.2 特征处理
user_df['InternetService']=user_df['InternetService'].str.replace('Fiber optic','Yes')
user_df['InternetService']=user_df['InternetService'].str.replace('DSL','Yes')
首先需要简化我们的属性值,将InternetService中的DSL数字网络,fiber optic光纤网络替换为Yes;将'OnlineSecurity','OnlineBackup','DeviceProtection','TechSupport', 中的no phoneservice 替换为no。
user_list=['OnlineSecurity','OnlineBackup','DeviceProtection','TechSupport']
for i in user_list:
user_df[i]=user_df[i].str.replace('No internet service','No')
第一类数据特征:
第一类特征的数据内容为:'yes' or 'no',属于这类特征的有:InternetService, OnlineSecurity, OnlineBackup, DeviceProtection,TechSupport, Churn。需要将'yes' or 'no'映射为0和1,方便后面计算。
InternetService=list(user_df['InternetService'])
OnlineSecurity=list(user_df['OnlineSecurity'])
OnlineBackup=list(user_df['OnlineBackup'])
DeviceProtection=list(user_df['DeviceProtection'])
TechSupport=list(user_df['TechSupport'])
Churn=list(user_df['Churn'])
SeniorCitizen=list(user_df['SeniorCitizen'])
for i in range(user_df.shape[0]):
if InternetService[i] == 'Yes':
InternetService[i] = 1
else:
InternetService[i] = 0
if DeviceProtection[i] == 'Yes':
DeviceProtection[i] = 1
else:
DeviceProtection[i] = 0
if OnlineSecurity[i] == 'Yes':
OnlineSecurity[i] = 1
else:
OnlineSecurity[i] = 0
if OnlineBackup[i] == 'Yes':
OnlineBackup[i] = 1
else:
OnlineBackup[i] = 0
if TechSupport[i] == 'Yes':
TechSupport[i] = 1
else:
TechSupport[i] = 0
if SeniorCitizen[i] == 'Yes': # 1为流失客户
SeniorCitizen[i] = 1
else:
SeniorCitizen[i] = 0
if Churn[i] == 'Yes': # 1为流失客户
Churn[i] = 1
else:
Churn[i] = 0
第二类数据特征:
第二特征的数据类型为离散型数据,且其数据内容为标称属性,标称型数据只提供了足够信息区分对象,而本身不具有任何顺序或数值计算的意义。属于这类特征的变量有:‘Contract’、 ‘Paymen tMethod’,这类变量采用One-Hot的方式进行编码,构造虚拟变量
Contract=user_df['Contract']
Contract_dummies=pd.get_dummies(Contract)
PaymentMethod=user_df['PaymentMethod']
PaymentMethod_dummies=pd.get_dummies(PaymentMethod)
第三类数据特征:
第三类的特征数据为数值型,数值型数据具备顺序以及加减运算的意义,目前属于这类特征的变量有:tenure,MonthlyCharges。可以采用连续特征离散化的处理方式,因为离散化后的特征对异常数据有更强的鲁棒性,可以降低过拟合的风险,使模型更稳定,预测的效果也会更好。数据离散化也称为分箱操作,其方法分为有监督分箱(卡方分箱、最小熵法分箱)和无监督分箱(等频分箱、等距分箱)。这里采用无监督分箱中的等频分箱进行操作。
tenure=list(user_df['tenure'])
tenure_cats=pd.qcut(tenure,6)
tenure_dummies=pd.get_dummies(tenure_cats)
MonthlyCharges=list(user_df['MonthlyCharges'])
MonthlyCharges_cats=pd.qcut(MonthlyCharges,5)
MonthlyCharges_dummies=pd.get_dummies(MonthlyCharges_cats)
最终得到模型的输入和输出特征:
Y=np.array(Churn).reshape(-1,1)
SeniorCitizen_x=np.array(SeniorCitizen).reshape(-1,1)
InternetService_x=np.array(InternetService).reshape(-1,1)
OnlineSecurity_x=np.array(OnlineSecurity).reshape(-1,1)
OnlineBackup_x=np.array(OnlineBackup).reshape(-1,1)
DeviceProtection_x=np.array(DeviceProtection).reshape(-1,1)
TechSupport_x=np.array(TechSupport).reshape(-1,1)
Contract_x=Contract_dummies.values
PaymentMethod_x=PaymentMethod_dummies.values
tenure_x=tenure_dummies.values
MonthlyCharges_x=MonthlyCharges_dummies.values
X=np.concatenate([SeniorCitizen_x,OnlineSecurity_x,OnlineBackup_x,InternetService_x,OnlineSecurity_x,TechSupport_x,TechSupport_x,Contract_x,PaymentMethod_x,tenure_x,MonthlyCharges_x],axis=1)
5. 建模
5.1 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=42)
x_train.shape
y_train.shape
5.2 用训练集训练模型
rf = RandomForestRegressor( random_state=42)
rf_tree = rf.fit(x_train,y_train)
5.3 用训练好的模型来预测测试集
predict_Y = rf.predict(x_test)
data = {'y_test':y_test,'predict_Y':predict_Y}
df = pd.DataFrame(data,columns=['test_Y','predict_Y'])
import sklearn.metrics as metrics
predict_Y = tree.predict(x_test)
predict_Y
print(metrics.classification_report(predict_Y, y_test))
随机森林精确度:
5.4 特征重要性可视化![](https://img-blog.csdnimg.cn/af949df09de14e5480a7590f52b550e3.png)
可以看到,对流失影响最大的是合同签订方式month-to-month,其次是电子支付方式,还有月消费,网络安全等等。
6. 结论与建议
结论建议主要是用户端和产品端两个方向。
6.1 用户端
1、针对老年人的流失率比年轻人高,且使用光纤网络服务后,流失率比未开通网络服务的还高。
针对老年人需要更精细化的服务,要提供附加的技术支持,及时有效的帮助他们解决难题,拉近与他们之间的距离,还可以选择开通老年人专线服务,提高老年人的留存率。
2、注册后的三个月内,用户流失最容易流失。
对此,可以在签订合同的时候给客户更多的优惠,让其增加签约时间,或者告知客户第二次签约的时候有神秘礼品,提高用户在网时长。继续往下延伸,还可以建立会员积分制度,累计消费获得积分,入网市时长达3个月、半年、一年者赠送更多积分,积分可以兑换更多的奖品。
3、月消费超过60元/月后,用户更容易流失。
特别是当用户为新注册的用户,前三个月内任何一次超额的消费都会让用户非常恼火,很容易造成流失,前三个月因给予一定的优惠策略,比如冲多少话费返多少话费这种形式,尽量在价格这个方面让用户觉得每家运营商都差不多。
6.2 产品端
1、缺少在线备份、技术支持、网络安全等条件下,用户的流失更严重。
在提供网络服务时,一定要尽可能的提供附加的技术支持,例如:在线备份、技术支持、在线安全等,在便捷用户上网的同时,保障他们的上网安全,个人隐私不被泄露。
2、使用电子账单支付的用户比其他方式更容易流失。
首先需要调查是否电子支付方式存在bug,功能设计的是否合理,还可以尝试去做nps用户调研,找到改进的方向,还可以在支付时推荐使用其他三种方式,避免客户在支付方式这个环节上大量流失。