一、背景

关于用户留存有这样一个观点,如果将用户流失率降低5%,公司利润将提升25%-85%。如今高居不下的获客成本让电信运营商遭遇“天花板”,甚至陷入获客难的窘境。随着市场饱和度上升,电信运营商亟待解决增加用户黏性,延长用户生命周期的问题。因此,电信用户流失分析与预测至关重要。

文章以分析为主,详细代码可查看一下百度云盘链接:

数据集:工作台 - Kesci.com​www.kesci.com

二、提出问题分析用户特征与流失的关系。

从整体情况看,流失用户的普遍具有哪些特征?

尝试找到合适的模型预测流失用户。

根据预测模型针性对流失用户给出增加用户黏性、预防流失的建议。

三、理解数据

四、数据清洗1. 完整性:单条数据是否存在空值,统计的字段是否完善。

2. 全面性:观察某一列的全部数值,通过常识来判断该列是否有问题,比如:数据定义、单位标识、数据本身。

3. 合法性:数据的类型、内容、大小的合法性。比如数据中是否存在非ASCII字符,性别存在了未知,年龄超过了150等。

4. 唯一性:数据是否存在重复记录,因为数据通常来自不同渠道的汇总,重复的情况是常见的。行数据、列数据都需要是唯一的。

1.完整性

# 查看数据是否存在Null,没有发现。

pd.isnull(customerDf).sum()

2.全面性

查看每一列数据的类型,发现TotalCharges的数据类型为字符串,按常识应该是数值类型,应该转化为浮点数类型。

# 查看每一列数据的类型

customerDf.info()

#customerDf.dtypes

#customerDf[['TotalCharges']].astype(float)

#ValueError: could not convert string to float:

依次检查各个字段的数据类型、字段内容和数量。最后发现“TotalCharges”(总金额)列有11个用户数据(有11个用户的TotalCharges对应的金额缺失)。

for x in customerDf.columns:

test=customerDf.loc[:,x].value_counts()

print('{0} 的行数是:{1}'.format(x,test.sum()))

print('{0} 的数据类型是:{1}'.format(x,customerDf[x].dtypes))

print('{0} 的内容是:\n{1}\n'.format(x,test))

#强制转换为数字,不可转换的变为NaN

customerDf['TotalCharges']=customerDf['TotalCharges'].convert_objects(convert_numeric=True)

转换后发现“TotalCharges”(总消费额)列有11个用户数据缺失,为NaN。

test=customerDf.loc[:,'TotalCharges'].value_counts().sort_index()

print(test.sum())

# 运行结果:7032

pd.isnull(customerDf['TotalCharges']).sum()

# 运行结果:11

根据前面检测出来的各个字段的数据类型、字段内容和数量,发现“TotalCharges”(总消费额)列有11个用户数据的用户的注册月数为0,推测是当月新入网用户。 根据一般经验,用户即使在注册的当月流失,也需缴纳当月费用。因此将这11个用户入网时长改为1,将总消费额填充为月消费额,符合实际情况。

print(customerDf.isnull().any())

print(customerDf[customerDf['TotalCharges']!=customerDf['TotalCharges']][['tenure','MonthlyCharges','TotalCharges']])

#将总消费额填充为月消费额

customerDf.loc[:,'TotalCharges'].replace(to_replace=np.nan,value=customerDf.loc[:,'MonthlyCharges'],inplace=True)

#查看是否替换成功

print(customerDf[customerDf['tenure']==0][['tenure','MonthlyCharges','TotalCharges']])

# 将‘tenure’入网时长从0修改为1

customerDf.loc[:,'tenure'].replace(to_replace=0,value=1,inplace=True)

print(pd.isnull(customerDf['TotalCharges']).sum())

print(customerDf['TotalCharges'].dtypes)

#获取数据类型的描述统计信息

customerDf.describe()

3. 合法性:数据的类型、内容、大小的合法性。比如数据中是否存在非ASCII字符,性别存在了未知,年龄超过了150等。

通过观察,无问题。

4. 唯一性:数据是否存在重复记录,因为数据通常来自不同渠道的汇总,重复的情况是常见的。行数据、列数据都需要是唯一的。

五、数据可视化分析

根据一般经验,将用户特征划分为用户属性、服务属性、合同属性,并从这三个维度进行可视化分析。

查看流失用户数量和占比

#保存图片

def savePic(name):

#bounding box_inches(边框英寸)设置,保存的图片去掉周围空白

plt.savefig('./desktop/{0}.png'.format(name), dpi=600,bbox_inches='tight')

plt.rcParams['figure.figsize']=6,6

plt.pie(customerDf['Churn'].value_counts(),labels=customerDf['Churn'].value_counts().index,autopct='%1.2f%%',explode=(0.1,0))

plt.title('Churn(Yes/No) Ratio')

savePic('Churn(Yes or No) Ratio')

plt.show()

# 使用catplot需要安装seaborn V0.9.0:conda install seaborn==0.9.0

churnDf=customerDf['Churn'].value_counts().to_frame()

x=churnDf.index

y=churnDf['Churn']

plt.bar(x,y,width = 0.5,color = 'c')

#用来正常显示中文标签(需要安装字库)

plt.rcParams['font.sans-serif']=['SimHei']

plt.rcParams.update({'font.size': 18})

plt.title('Churn(Yes/No) Num')

for a,b in zip(x,y):

plt.text(a,b+10,'%.0f' % b, ha='center', va= 'bottom')

savePic('Churn(Yes or No) Num')

plt.show()

流失用户占到总用户的25.64%,本数据集数据不平衡数据集。

5.1 用户属性分析

5.1.1属性:SeniorCitizen、gender1-是老年用户;0-不是老年用户

小结(5.1.1):性别差异对客户流失率的影响不大,

是否是老年用户,对流失率影响相对较大,年老用户流失占显著高于年轻用户

5.1.2属性:Partner and Dependents

小结(5.1.2):有伴侣的用户流失占比低于无伴侣用户; 有家属的用户流失占比低于无家属用户。

5.2服务属性分析

5.2.1 属性:tenure、MonthlyCharges、TotalCharges

小结(5.2.1)注册月数越长,流失率越小;

总消费额在3000元以上,客户流失率越小;

月度消费额在70~110,流失率较高。

5.2.2 属性:InternetService

小结(5.2.2)光纤用户的流失占比较高

5.2.3 网络附加属性

小结(5.2.3)有无电话服务,对客户流失率影响不大;

当客户有多条线路服务的时候,流失率较大;

当为客户附加提供,在线安全、设备保护、技术支持时,客户流失率相对较低;

为客户附加提供流媒体电视、电影的时候,客户流失率相对较低。

5.3 合同属性分析

5.3.1 属性:PaperlessBilling

小结(5.3.1)使用无纸的客户流失率较高,推测该方式的使用体验较为一般;

合同期限越长的客户流失率越低。

5.3.2 属性:PaymentMethod

小结(5.3.2)签订合同方式对客户流失率影响为:按月签订 > 按一年签订 > 按两年签订,证明长期合同最能保留客户。

5.3.4 属性:MonthlyCharges&TotalCharges

小结(5.3.4)月度付费在70到110之间的流失率较高;

付费总额越高,客户流失率越低。

通过以上分析,可以得到较高流失率的人群特征,具有这些特征的人群需要对其进行运营,增加用户黏性,延长其生命周期价值。

六.构建模型

对数据集进一步清洗和提取特征,通过特征选取对数据进行降维,采用机器学习模型应用于测试数据集,然后对构建的分类模型准确性进行分析。

6.1 数据清洗

考虑到pandas已有想要的id列,我们这里可以删除想要的列customerID。

customerID=customerDf['customerID']

customerDf.drop(['customerID'],axis=1, inplace=True)

6.2 离散数据(one-hot 编码)

6.3 连续数据集(标准化处理)

标准化数据,保证每个维度的特征数据方差为1,均值为0,使得预测结果不会被某些维度过大的特征值而主导。

6.4 模型测试

plt.figure(figsize=(16,8))

df_processed.corr()['Churn'].sort_values(ascending=False).plot(kind='bar')

plt.show()

6.4.1 特征选取

许多特征可能是无用的或嘈杂的,删除它们可能会获得更好预测,尝试删除这些特征。

# 特征选择

dropFea = ['gender','PhoneService',

'OnlineSecurity_No internet service', 'OnlineBackup_No internet service',

'DeviceProtection_No internet service', 'TechSupport_No internet service',

'StreamingTV_No internet service', 'StreamingMovies_No internet service',

#'OnlineSecurity_No', 'OnlineBackup_No',

#'DeviceProtection_No','TechSupport_No',

#'StreamingTV_No', 'StreamingMovies_No',

]

dfCate.drop(dropFea, inplace=True, axis =1)

#最后一列是作为标识

target = dfCate['Churn'].values

#列表:特征和1个标识

columns = dfCate.columns.tolist()

6.4.2 构建训练集和测试集

# 列表:特征

columns.remove('Churn')

# 含有特征的DataFrame

features = dfCate[columns].values

# 30% 作为测试集,其余作为训练集

# random_state = 1表示重复试验随机得到的数据集始终不变

# stratify = target 表示按标识的类别,作为训练数据集、测试数据集内部的分配比例

train_x, test_x, train_y, test_y = train_test_split(features, target, test_size=0.30, stratify = target, random_state = 1)

6.4.3 构建多个分类器

# 构造各种分类器

classifiers = [

SVC(random_state = 1, kernel = 'rbf'),

DecisionTreeClassifier(random_state = 1, criterion = 'gini'),

RandomForestClassifier(random_state = 1, criterion = 'gini'),

KNeighborsClassifier(metric = 'minkowski'),

AdaBoostClassifier(random_state = 1),

]

# 分类器名称

classifier_names = [

'svc',

'decisiontreeclassifier',

'randomforestclassifier',

'kneighborsclassifier',

'adaboostclassifier',

]

# 分类器参数

#注意分类器的参数,字典键的格式,GridSearchCV对调优的参数格式是"分类器名"+"__"+"参数名"

classifier_param_grid = [

{'svc__C':[0.1], 'svc__gamma':[0.01]},

{'decisiontreeclassifier__max_depth':[6,9,11]},

{'randomforestclassifier__n_estimators':range(1,11)} ,

{'kneighborsclassifier__n_neighbors':[4,6,8]},

{'adaboostclassifier__n_estimators':[70,80,90]}

]

def GridSearchCV_work(pipeline, train_x, train_y, test_x, test_y, param_grid, score = 'accuracy_score'):

response = {}

gridsearch = GridSearchCV(estimator = pipeline, param_grid = param_grid, cv=3, scoring = score)

# 寻找最优的参数 和最优的准确率分数

search = gridsearch.fit(train_x, train_y)

print("GridSearch 最优参数:", search.best_params_)

print("GridSearch 最优分数: %0.4lf" %search.best_score_)

#采用predict函数(特征是测试数据集)来预测标识,预测使用的参数是上一步得到的最优参数

predict_y = gridsearch.predict(test_x)

print(" 准确率 %0.4lf" %accuracy_score(test_y, predict_y))

response['predict_y'] = predict_y

response['accuracy_score'] = accuracy_score(test_y,predict_y)

return response

for model, model_name, model_param_grid in zip(classifiers, classifier_names, classifier_param_grid):

#采用 StandardScaler 方法对数据规范化:均值为0,方差为1的正态分布

pipeline = Pipeline([

#('scaler', StandardScaler()),

#('pca',PCA),

(model_name, model)

])

result = GridSearchCV_work(pipeline, train_x, train_y, test_x, test_y, model_param_grid , score = 'accuracy')GridSearch 最优参数: {'svc__C': 0.1, 'svc__gamma': 0.01}

GridSearch 最优分数: 0.7347

准确率 0.7345

GridSearch 最优参数: {'decisiontreeclassifier__max_depth': 6}

GridSearch 最优分数: 0.7728

准确率 0.7766

GridSearch 最优参数: {'randomforestclassifier__n_estimators': 4}

GridSearch 最优分数: 0.7556

准确率 0.7416

GridSearch 最优参数: {'kneighborsclassifier__n_neighbors': 8}

GridSearch 最优分数: 0.7606

准确率 0.7681

GridSearch 最优参数: {'adaboostclassifier__n_estimators': 70}

GridSearch 最优分数: 0.7852

准确率 0.7823

对分类器进行参数调优和评估,最后得到试用AdaBoostClassifier(n_estimators=80)效果最好。

6.5 模型预测

# 使用上述得到的最优模型

model = AdaBoostClassifier(n_estimators=80)

model.fit(train_x,train_y)

# 提取customerID

pred_id = customerID.tail(10)

# 提取预测数据集特征(如果有预测数据集,可以一并进行数据清洗和特征提取)

pred_x = dfCate.drop(['Churn'],axis=1).tail(10)

# 预测值

pred_y = model.predict(pred_x)

# 预测结果

predDf = pd.DataFrame({'customerID':pred_id, 'Churn':pred_y})

print(predDf)

七、结论和建议

根据以上分析,得到高流失率用户的特征:用户属性:老年用户,未婚用户,无亲属用户更容易流失;

服务属性:无互联网增值服务,在网时长小于半年,互联网提供商为光纤用户,无附加流媒体电视、电影服务。

合同属性:签订的合同期较短,采用电子支票支付,是电子账单,月租费约70-110元的客户容易流失;

其它属性对用户流失影响较小。

针对上述结论,从业务角度给出相应建议:根据预测模型,构建一个高流失率的用户列表。通过用户调研推出一个最小可行化产品功能,并邀请种子用户进行试用。

用户方面:针对老年用户、无亲属、无伴侣用户的特征推出定制服务如亲属套餐、温暖套餐等,一方面加强与其它用户关联度,另一方对特定用户提供个性化服务。

服务方面:针对新注册用户,推送半年优惠如赠送消费券,以度过用户流失高峰期。网络附加哦服务,一方面用户承诺免费网络升级和赠送电视、电影等包月服务以提升用户黏性,另一方面针对在线安全、在线备份、设备保护、技术支持等增值服务,应重点对用户进行推广介绍,如首月/半年免费体验。

合同方面:针对单月合同用户,建议推出年合同付费折扣活动,将月合同用户转化为年合同用户,提高用户在网时长,以达到更高的用户留存。 针对采用电子支票支付用户,建议定向推送其它支付方式的优惠券,引导用户改变支付方式。

参考资料:https://www.kaggle.com/jsaguiar/churn-prediction-tutorial-with-sklearn​www.kaggle.com机器学习:数据预处理之独热编码(One-Hot)_慕课手记​www.imooc.com南桥那人:电信用户流失分析与预测​zhuanlan.zhihu.com

python市场饱和_数据分析项目02-客户流失率(Python)相关推荐

  1. python分类汇总_数据分析番外篇13_利用Python实现分类汇总

    自己建立了一个数据分析兴趣小组群,在分享了一篇有关Python的介绍后,这两天大家的学习热情高涨,于是纷纷将自己的问题扔到群里诱使大家来解决,比如:如何代码实现去除文本里面的多余空格,如何将一个27万 ...

  2. 7.Python数据分析项目之银行客户流失分析

    1.总结 预测类数据分析项目 流程 具体操作 基本查看 查看缺失值(可以用直接查看方式isnull.图像查看方式查看缺失值missingno).查看数值类型特征与非数值类型特征.一次性绘制所有特征的分 ...

  3. python数据分析实例:客户流失预警模型

    python数据分析实例:客户流失预警模型 客户流失是电信行业最重要的服务方面之一.客户流失的广义说法是因为客户自己或运营商违反服务协议而终止客户服务的行为. 流失预测流程一共分为四个步骤,分别为(1 ...

  4. SaaS企业如何降低客户流失率?

    续费率是SaaS企业的生命线,如何把续费率/续约率持续提升是所有SaaS公司一同面临的挑战,随着疫情的到来,企业支出缩紧,裁员等现象对本就不理想的续费指标更是雪上加霜,以客户为中心几乎是所有人挂在嘴边 ...

  5. 一文看懂机器学习流程(客户流失率预测)

    点击上方"程序员大咖",选择"置顶公众号" 关键时刻,第一时间送达! 定义问题 客户流失率问题是电信运营商面临得一项重要课题,也是一个较为流行的案例.根据测算, ...

  6. 弘辽科技:淘宝客户流失率高怎么办?

    商家开店铺的时候,很怕的是老客户流失了.或者说经常购买的人不买了,这是淘宝店铺的客户流失.那么当我们遇到淘宝的客户流失率很高的时候该怎么办呢?有什么样的因素会造成影响呢? 淘宝客户流失率高怎么办? 1 ...

  7. 【用户运营】用这4个最佳客户服务策略,减少客户流失率

    关键词:客户服务.客户流失率.用户运营 根据你所处的行业,获取一个新客户的成本可能比保留一个现有客户的成本高25%. 这是有道理的:你可以花几周时间研究如何让新客户进入你的企业,并投入大量的时间和精力 ...

  8. 跨境电商如何减少客户流失率:成功的5种保留策略

    关键词:跨境电商.客户流失率 经营一家跨境电商企业常常感觉就像一个漏水的容器.无论您在顶部倾注了多少客户,这始终是一个不断耗尽底部的百分比. 这被称为客户流失--它使可持续增长成为品牌面临的主要挑战. ...

  9. 如何降低客户流失率高的问题

    企业在业务拓展过程中,最为头疼的即为降低"客户流失率".即便用户与企业已经进行过多次互动,依然会在不同时刻,毫无缘由的默默离开.而用户的离开真的是"毫无缘由"吗 ...

最新文章

  1. Nimbus/Supervisor本地目录结构
  2. 算法导论——lec 10 图的基本算法及应用
  3. tomact如何处理一个http请求?
  4. 图象关于y轴对称是什么意思_数学概念丨“图象”与“图像”是有区别的 ,你知道吗?...
  5. 微信知识付费小程序博客源码(带299条数据)
  6. 7-7 印度大壶节 (25 分)
  7. win10执行npm出现Error: EBUSY: resource busy or locked 错误解决方法
  8. SpringBoot实战(九)之Validator
  9. 思科ASA防火墙升级为云端防火墙
  10. JFlash烧录不知名的ARM芯片
  11. 求两点连线与其中一点为球心球的交点——赋MATLAB代码
  12. 崩坏3服务器维护2月8号,《崩坏3》2月8日更新内容 符华月轮正式上线
  13. 卷积神经网络CNN简图
  14. 中山マミ - 咲く未来
  15. 唐太宗管理之道:收人,收心,收天下
  16. 11、Altiris cms 7.0 系统监控
  17. IDA调试修改内存数据
  18. 商用三相水表行业调研报告 - 市场现状分析与发展前景预测
  19. 上班用“蝙蝠侠电话”沟通是一种怎样的体验?
  20. Python08--文件读取及写入操作

热门文章

  1. 如何利用 Azure 为 TEASOFT视频配音?
  2. 通过一个word模板来生成新的word并且填充内容
  3. landsat8与landsat7波段对比
  4. IAM 策略文档学习笔记
  5. (十三)常见开发工具及QC中站点管理、项目自定义管理常见操作
  6. 前端开发者最常用的六款IDE
  7. Java可以用到军事方面吗_恭喜长征五号遥三运载火箭发射,浅谈编程语言在军事方面的运用!...
  8. 防止Web攻击,做好HTTP安全标头
  9. Linux Qt cannot find -lGL 解决方案
  10. ① 尚品汇的后台管理系统【尚硅谷】【Vue】