美文网首页python可视化
携程客户流失分析

携程客户流失分析

作者: 余三书 | 来源:发表于2019-02-15 11:48 被阅读0次

    第一部分:

    1.行业现状

        在今天产品高度同质化的阶段,市场竞争不断加剧,企业与企业之间的竞争,主要集中在对客户的争夺上。“用户就是上帝”促使众多的企业不惜代价去争夺尽可能多的新客户。

    但是,在企业不惜代价发展新用户的过程中,往往会忽视已有老用户的流失情况,结果就导致出现新用户在源源不断的增加,辛苦找来的老用户却在悄然无声的流失的窘状。

        如何处理客户流失问题,成为一个非常重要的课题。

        那么,我们如何从数据汇总挖掘出有价值的信息,来防止客户流失呢?

    因为我们此次数据分析的主题是携程酒店客户流失分析,所以,我们先来简单了解一下行业情况:

    携程网曾经占据在线酒店的主要市场,但是随着美团在2017年加入,格局逐很快被打破。

    从下图可以看出:

    行业TOP3的用户重合率比较低,用户差异度明显。

    用户与市场竞争具有很大的相关性。

    2.数据概况:

    本数据集合userlostprob_data.csv,为携程网2016年5月16至21日期间一周的访问数据。

    本数据集共有总的数据共有689945行,49列,包含样本id,label以及47个变量特征。

    考虑到保护用户隐私,数据不提供用户id,并经过了数据脱敏处理,和实际的订单、浏览量、转化率有一些差距,但是并不影响问题的可解性。

    3.项目目的:

    除了前面提到的挖掘出影响用户流失的关键因素,还包括预测客户的转化效果以及用K-means对用户进行画像,并针对不同的用户类别,提出可行的营销建议。


    第二部分:

    1.理解数据

    对理解数据,了解各个字段的业务含义是首先要做的事情。

    userlostprob_data.csv 里面的变量比较多,最好进行分类了解。经过研究发现,此数据集的字段可以大概分成三种类别,分别是:客户行为指标,订单相关指标,酒店相关指标。

    如下图:

    当然,并不是简单的一个分类就可以完全了解所有的字段的,最好是逐个字段解析,一个比较好的办法就是每个字段按照自己的理解举出例子来理解。

    事实上,当我们拿到的数据,里面的字段名称是英文的,而且英文字段由单词拼接而成,这增加了阅读和理解的难度,为了降低难度,我们可以把单词分开,然后再理解。

    2.查看数据

    2.1 引入约定

    import pandas as pd

    import numpy as np

    import matplotlib.pyplot as plt

    %matplotlib inline

    2.2 导入数据

    import os

    os.chdir(r'/Users/Desktop/data/')

    data=pd.read_table('userlostprob.txt')

    2.3 查看数据

    data.head()

    查看统计情况

    data.describe()

    查看缺失情况,并统计

    data_count = data.count()

    na_count = len(data) - data_count

    na_rate = na_count/len(data) #缺失比例

    a=na_rate.sort_values(ascending=False) #排序

    a1=pd.DataFrame(a)

    a1

     绘图查看缺失情况

    #用来正常显示中文标签

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

    x=data.shape[1]

    fig = plt.figure(figsize=(8,12))#图形大小

    plt.barh(range(x),a1[0], color= 'steelblue', alpha = 1)

    # 添加轴标签

    plt.xlabel( '数据缺失占比')

    # 添加刻度标签

    columns1=a1.index.values.tolist() # 列名称

    plt.yticks(range(x),columns1)

    #设置X轴的刻度范围

    plt.xlim([ 0, 1])

    # 为每个条形图添加数值标签

    for x,y in enumerate(a1[0]):

        plt.text(y,x,'%.3f' %y,va= 'bottom')

    plt.show()

    从上图可以看出缺失值的分布情况:

    数据集的缺失情况比较严重,有44列存在缺失情况,其中近7天用户历史订单数:historyvisit_7ordernum缺失为88%,20列缺失值在20-55%,23列缺失值占比小于20%。

    3.数据预处理

    3.1 衍生变量

    添加新列:提前预定=入住时间-访问时间

    #添加新列:提前预定

    data['d'] = pd.to_datetime(data['d'])

    data['arrival'] = pd.to_datetime(data['arrival'])

    data['Advance booking']=(data['arrival']-data['d']).dt.days

    3.2 删除缺失值比例88%的列historyvisit_7ordernum

    data=data.drop(["historyvisit_7ordernum"],axis=1)

    3.3 过滤无用的维度

    filter_feature = ['sampleid','d','arrival'] # 过滤无用的维度

    features = []

    for x in data.columns: # 取特征

        if x not in filter_feature:

            features.append(x)

    data_x = data[features]  #共47个特征

    data_y = data['label']

     3.4 异常值负数的处理

    customer_value_profit、ctrip_profits替换为0

    delta_price1、delta_price2、lowestprice按中位数处理:

    data_x.loc[data_x.ctrip_profits<0,'ctrip_profits'] = 0

    data_x.loc[data_x.customer_value_profit<0,'customer_value_profit'] = 0

    data_x.loc[data_x.delta_price1<0,'delta_price1'] = data_x['delta_price1'].median()

    data_x.loc[data_x.lowestprice<0,'lowestprice'] = data_x['lowestprice'].median()

    data_x.loc[data_x.delta_price2<0,'delta_price2'] = data_x['delta_price2'].median()

    3.5缺失值填充

    查看数据分布情况

    import matplotlib.pyplot as plt

    for i in range(0,47):

        plt.figure(figsize=(2,1),dpi=100)

        plt.hist(data_x[data_x.columns[i]].dropna().get_values())

        plt.xlabel(data_x.columns[i])

    plt.show()

    示例

    趋于正态分布的字段,使用均值填充:

    3个字段businessrate_pre2、cancelrate_pre、businessrate_pre

    data_x['businessrate_pre2']=data_x['businessrate_pre2'].fillna(data_x['businessrate_pre2'].mean())

    data_x['cancelrate_pre']=data_x['cancelrate_pre'].fillna(data_x['cancelrate_pre'].mean())

    data_x['businessrate_pre']=data_x['businessrate_pre'].fillna(data_x['businessrate_pre'].mean())

    右偏分布的字段,使用中位数填充:

    def filling(data):

        for i in range(0,47):

            data_x[data_x.columns[i]]=data_x[data_x.columns[i]].fillna(data[data_x.columns[i]].median())

        return data_x

    filling(data_x)

    3.6 检查缺失值填充情况

    #检验填充缺失20%以下后缺失情况,并统计

    data_count2 = data_x.count()

    na_count2 = len(data_x) - data_count2

    na_rate2 = na_count2/len(data_x) #缺失比例

    aa2=na_rate2.sort_values(ascending=False) #排序

    a3=pd.DataFrame(aa2)

    a3

    查看可知,缺失值数据已填充完毕。

    3.7  极值处理

    盖帽法处理极值:

    data1 =np.array(data_x)  #把数据转为array

    #盖帽法 i是数据列数里的第几列, j是数据第i列里的第几个数

    for i in range(0,len(data1[0])):    #i从0到总列数循环

        a=data1[:,i]                    #索引data1里的第i列并放入a

        b=np.percentile(a,1)        #计算a里的1%分位数

        c=np.percentile(a,99)      #计算a里的99%分位数

        for j in range(0,len(data1[:,0])): #j从0到一列数据的总个数循环

                if a[j]<b:          #如果data1里的第i列里的第j个数小于1%分位数

                    a[j]=b          #就把data1里的第i列里的第j个数换成1%分位数

                elif a[j]>c:        #如果data1里的第i列里的第j个数大于99%分位数

                    a[j]=c          #就把data1里的第i列里的第j个数换成99%分位数

                else:

                    a[j]            #如果大于1%分位数小于99%分位数的值,则返回原值

              # print(a[j])

    data1

    data1=pd.DataFrame(data1,columns=features) #换回DataFrame columns是每列数据的列名

    #data1.dtypes    查看数据格式

    data1.describe()  #查看最大值最小值是否替换成功

    data1.info()

    plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签

    plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号

    for i in range(0,47):

        plt.figure(figsize=(4,8),dpi=100)

        plt.boxplot(data1[data1.columns[i]].dropna().get_values())#画箱线图

        plt.xlabel(data1.columns[i])

    plt.show() #展示箱线图

    #查看最小值是否不为负数

    data1['ctrip_profits'].min()

    data1['customer_value_profit'].min()

    data1['delta_price1'].min()

    data1['lowestprice'].min()

    data1['delta_price2'].min()


    第三部分

    1.相关系数

    生成相关系数矩阵并保存

    corrdf = data1.corr() 

    corrdf

    corrdf.to_csv( '相关性矩阵.csv' , index = False )

    生成label与其他变量的相关系数,并降序排序

    corrdf['label'].sort_values(ascending =False)

    去除相关系数小于0.01的特征

    delete_columns=[]

    for i in range(1,corrdf.shape[0]):

        if abs(corrdf.iloc[0,i])<0.01:

            delete_columns.append(data1.columns[i])

    data1.drop(delete_columns,axis=1,inplace=True)

    去除x与x之间相关性大于0.9,且与y的相关性的绝对值比较小的特征

    delete_columns2 = ["historyvisit_totalordernum","delta_price1","cityuvs"]

    data1.drop(delete_columns2,axis=1,inplace= True)

    2.标准化处理

    为了使数据适应线性分类模型,对数据做标准化处理:

    from sklearn.preprocessing import StandardScaler

    y=data1.label

    x=data1.drop('label',axis=1)

    scaler = StandardScaler()

    scaler.fit(x)

    x= scaler.transform(x)

    data1.head()

    data1.describe()


    第四部分 

    1.导入模型包,建模:

    from sklearn.linear_model import LogisticRegression

    from sklearn.ensemble import RandomForestClassifier

    from sklearn.svm import SVC

    #import xgboost as xgb

    from sklearn import metrics

    from sklearn.model_selection import train_test_split, GridSearchCV

    x_train,x_test,y_train,y_test = train_test_split(x,y,test_size= .2,random_state=1234)

    2.逻辑回归模型

    lr = LogisticRegression()

    lr.fit(x_train,y_train)

    y_lr = lr.predict_proba(x_test)[:,1]

    fpr_lr,tpr_lr,threshold_lr = metrics.roc_curve(y_test,y_lr)

    auc_lr = metrics.auc(fpr_lr,tpr_lr)

    score_lr = metrics.accuracy_score(y_test,lr.predict(x_test))

    print([score_lr,auc_lr])

    结果:[0.7400155084825603, 0.6995933154475564]

    3.随机森林模型:

    rfc = RandomForestClassifier()

    rfc.fit(x_train,y_train)

    y_rfc = rfc.predict_proba(x_test)[:,1]

    fpr_rfc,tpr_rfc,threshold_rfc = metrics.roc_curve(y_test,y_rfc)

    auc_rfc = metrics.auc(fpr_rfc,tpr_rfc)

    score_rfc = metrics.accuracy_score(y_test,rfc.predict(x_test))

    print([score_rfc,auc_rfc])

    结果:[0.9061157048750262, 0.952069158341962]

    用随机森林分析影响客户流失的因素:

    importance = rfc.feature_importances_

    indices = np.argsort(importance)[::-1]

    features = data1.columns

    for f in range(x.shape[1]):

        print(("%2d) %-*s %f" % (f + 1, 30, features[f], importance[indices[f]])))

    4.朴素贝叶斯模型:

    from sklearn.naive_bayes import GaussianNB

    gnb = GaussianNB()

    gnb.fit(x_train,y_train)

    y_gnb = gnb.predict_proba(x_test)[:,1]

    fpr_gnb,tpr_gnb,threshold_gnb = metrics.roc_curve(y_test,y_gnb)

    auc_gnb = metrics.auc(fpr_gnb,tpr_gnb)

    score_gnb = metrics.accuracy_score(y_test,gnb.predict(x_test))

    print([score_gnb,auc_gnb])

    结果:[0.6506315720818326, 0.6686088984441764]

    5.决策树模型:

    from sklearn import tree

    dtc = tree.DecisionTreeClassifier()

    dtc.fit(x_train,y_train)

    y_dtc = dtc.predict_proba(x_test)[:,1]

    fpr_dtc,tpr_dtc,threshod_dtc= metrics.roc_curve(y_test,y_dtc)

    metrics.accuracy_score(y_test,dtc.predict(x_test))

    结果:0.8852082412366203

    6.画图对比:

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

    fig = plt.plot()

    plt.plot(fpr_rfc,tpr_rfc,label='rfc')#随机森林

    plt.plot(fpr_dtc,tpr_dtc,label='dtc')#决策树

    plt.plot(fpr_lr,tpr_lr,label='lr')#逻辑回归

    plt.plot(fpr_gnb,tpr_gnb,label='gnp')#朴素贝叶斯模型

    #plt.plot(fpr_xgb,tpr_xgb,label='xgb')#XGBOOST

    plt.legend(loc=0)#在合适的位置放置图例

    plt.xlabel('False Positive Rate')

    plt.ylabel('True Positive Rate')

    plt.title('ROC carve');

    plt.show()


    第五部分

    1.K-means用户画像:

    dat=pd.concat((df['consuming_capacity'],df['customer_value_profit'],df['ordercanncelednum'],df['ordercanceledprecent'],df['ctrip_profits'],

                  df['historyvisit_7ordernum'],df['historyvisit_totalordernum'],

                  df['lastpvgap'],df['lasthtlordergap']),axis=1)

    dat.to_csv('rfm',index=False)

    from sklearn.cluster import KMeans

    data=pd.read_csv('rfm')

    Kmodel=KMeans(3)

    Kmodel.fit(data)

    Kmodel.cluster_centers_.to_csv()

    结果:

    低价值用户占比居多,可结合该群体流失情况分析流失客户因素,进行   该群体市场的开拓。

    新用户,是潜在客户群体,可对该部分用户实施一些营销策略。

    高价值用户和追求高品质用户,能给我们带来较优的收益,

    可对这两类群体实施个性化营销策略。

    3.高价值用户分析

    用户描述:

        商务人群订单数多,登陆时间长,访问次数多,提前预定时间短,但退单次数较多。

    退单次数多的原因:

        该类用户以商务人群居多,商务活动的不确定性较高,前一秒要出差,后一秒就不用了。

    建议:

    因为这类用户能给我们带来较优的收益,可对这类群体实施个性化营销策略。如:

    Ø1.为客户提供更多差旅地酒店信息。

    Ø2.推荐口碑好、性价比高的商务连锁酒店房源吸引用户。

    Ø3.在非工作日的11点、17点等日间流量小高峰时段进行消息推送。

    4.追求高品质用户分析

    用户描述:

    非商务类用户,这类用户的消费能力强,注重酒店星级,但对价格比较敏感。

    价格敏感指数偏高原因:

    价格敏感指数偏高,有可能是我们对高星级酒店做的价格优惠活动较多。

    可适当减少对高星级酒店的价格优惠。

    建议:

    此类用户能给我们带来较优的收益,可对这类群体实施个性化营销策略。

    Ø1.推送高端酒店以及当地的旅行资讯,吸引用户关注。

    Ø2.和景区酒店代理商合作,针对此类用户制定个性化推荐。

    Ø3.可在节假日前两、三星期定期推送国外高星级酒店。

    5.新用户分析:

    用户描述:

    近期有下单,访问次数少,偏好低价格的酒店,对酒店的星级要求偏低,消费能力低。

    建议:

    Ø1.此类用户是潜在客户,建议把握用户初期体验(如初期消费有优惠、打卡活动等),还可以定期推送实惠的酒店给此类用户,以培养客户消费惯性为主。

    Ø2.不建议花费过多营销预算。

    6.低价值用户:

    用户描述:

    非旅游爱好者,这类客户属于低价值沉默客户,产品可按常规流失客户处理。

    建议:

    Ø1.由于这部分用户占比较多,可结合该群体流失情况分析流失客户因素,进行该群体市场的开拓。

    Ø2.提供低价酒店促销活动为主。

    Ø3.暂不对这部分客户这部分用户做特定渠道运营。

    相关文章

      网友评论

        本文标题:携程客户流失分析

        本文链接:https://www.haomeiwen.com/subject/ithpeqtx.html