数据分析-航空公司客户价值分析

  1. 对数据进行基本的探索
    #对数据进行基本的探索
    #返回缺失值个数以及最大最小值
    import pandas as pd
    
    datafile = 'D:/人工智能&软件工程/数据挖掘与分析/data/air_data.csv'#读取数据
    resultfile = 'D:/人工智能&软件工程/数据挖掘与分析/tmp/explore学号:3041.csv'#对航空数据进行探索
    
    #读取原始数据,指定UTF-8编码(需要用文本编译器将数据装换为UTF-8编码)
    data = pd.read_csv(datafile,encoding = 'utf-8')
    
    #包括对数据的基本描述,percentiles参数是指定计算多少的分位数表(如1/4分位数,中位数等)
    explore = data.describe(percentiles = [],include = 'all').T #T是转置,转置后更方便查阅
    explore['null'] = len(data)-explore['count'] #describe()函数自动计算非空值数,需要手动计算空值数
    
    explore = explore[['null', 'max', 'min']]
    explore.columns = [u'空值数', u'最大值', u'最小值'] #表头重命名
    '''这里只选取部分探索结果。
    describe()函数自动计算的字段有count(非空值数)、unique(唯一值数)、top(频数最高者)、freq(最高频数)、mean(平均值)、std(方差)、min(最小值)、50%(中位数)、max(最大值)'''
    
    explore.to_csv('D:/人工智能&软件工程/数据挖掘与分析/tmp/explore学号:3041.csv') #导出结果
    print(explore)
                               空值数        最大值    最小值
    MEMBER_NO                  0.0    62988.0    1.0
    FFP_DATE                     0        NaN    NaN
    FIRST_FLIGHT_DATE            0        NaN    NaN
    GENDER                       3        NaN    NaN
    FFP_TIER                   0.0        6.0    4.0
    WORK_CITY                 2269        NaN    NaN
    WORK_PROVINCE             3248        NaN    NaN
    WORK_COUNTRY                26        NaN    NaN
    AGE                      420.0      110.0    6.0
    LOAD_TIME                    0        NaN    NaN
    FLIGHT_COUNT               0.0      213.0    2.0
    BP_SUM                     0.0   505308.0    0.0
    EP_SUM_YR_1                0.0        0.0    0.0
    EP_SUM_YR_2                0.0    74460.0    0.0
    SUM_YR_1                 551.0   239560.0    0.0
    SUM_YR_2                 138.0   234188.0    0.0
    SEG_KM_SUM                 0.0   580717.0  368.0
    WEIGHTED_SEG_KM            0.0  558440.14    0.0
    LAST_FLIGHT_DATE             0        NaN    NaN
    AVG_FLIGHT_COUNT           0.0     26.625   0.25
    AVG_BP_SUM                 0.0    63163.5    0.0
    BEGIN_TO_FIRST             0.0      729.0    0.0
    LAST_TO_END                0.0      731.0    1.0
    AVG_INTERVAL               0.0      728.0    0.0
    MAX_INTERVAL               0.0      728.0    0.0
    ADD_POINTS_SUM_YR_1        0.0   600000.0    0.0
    ADD_POINTS_SUM_YR_2        0.0   728282.0    0.0
    EXCHANGE_COUNT             0.0       46.0    0.0
    avg_discount               0.0        1.5    0.0
    P1Y_Flight_Count           0.0      118.0    0.0
    L1Y_Flight_Count           0.0      111.0    0.0
    P1Y_BP_SUM                 0.0   246197.0    0.0
    L1Y_BP_SUM                 0.0   259111.0    0.0
    EP_SUM                     0.0    74460.0    0.0
    ADD_Point_SUM              0.0   984938.0    0.0
    Eli_Add_Point_Sum          0.0   984938.0    0.0
    L1Y_ELi_Add_Points         0.0   728282.0    0.0
    Points_Sum                 0.0   985572.0    0.0
    L1Y_Points_Sum             0.0   728282.0    0.0
    Ration_L1Y_Flight_Count    0.0        1.0    0.0
    Ration_P1Y_Flight_Count    0.0        1.0    0.0
    Ration_P1Y_BPS             0.0   0.999989    0.0
    Ration_L1Y_BPS             0.0   0.999993    0.0
    Point_NotFlight            0.0      140.0    0.0
  2. 数据的分布分析
    #7-2
    #对数据的分布分析
    import pandas as pd
    import matplotlib.pyplot as plt
    datafile = 'D:/人工智能&软件工程/数据挖掘与分析/data/air_data.csv'#航空原始数据,第一行为属性标签
    
    #读取原始数据,指定UTF-8编码(需要用文本编译器将数据装换为UTF-8编码)
    data = pd.read_csv(datafile,encoding = 'utf-8')
    # 客户信息类别
    # 提取会员入会年份
    from datetime import datetime
    ffp = data['FFP_DATE'].apply(lambda x:datetime.strptime(x, '%Y/%m/%d'))
    ffp_year = ffp.map(lambda x : x.year)
    
    print(ffp_year)
    #绘制各年份会员入会人数直方图
    fig = plt.figure(figsize=(8, 5))  #设置画布大小
    plt.hist(ffp_year, bins='auto', color='#0504aa')
    plt.xlabel('年份')
    plt.ylabel('入会人数')
    plt.rcParams['font.sans-serif'] = ['SimHei']#正常显示中文
    plt.title('各年份会员入会人数学号:3041')
    plt.show()
    plt.close()
    0        2006
    1        2007
    2        2007
    3        2008
    4        2009
             ... 
    62983    2011
    62984    2010
    62985    2006
    62986    2013
    62987    2013
    Name: FFP_DATE, Length: 62988, dtype: int64
    
     
  3. 绘制会员性别比例饼图
    #提取会员不同性别人数
    male = pd.value_counts(data['GENDER'])['']
    female = pd.value_counts(data['GENDER'])['']
    #绘制会员性别比例饼图
    fig = plt.figure(figsize=(7, 4))  #设置画布大小
    plt.pie([male, female], labels=['', ''], colors=['lightskyblue', 'lightcoral'], autopct='%1.1f%%')
    plt.rcParams['font.sans-serif'] = ['SimHei']#正常显示中文
    plt.title('会员性别比例学号:3041')
    plt.show()
    plt.close()

  4. 绘制会员各级别人数条形图
    #提取不同级别会员的人数
    lv_four = pd.value_counts(data['FFP_TIER'])[4]
    lv_five = pd.value_counts(data['FFP_TIER'])[5]
    lv_six = pd.value_counts(data['FFP_TIER'])[6]
    #绘制会员各级别人数条形图
    fig = plt.figure(figsize=(8,5))  #设置画布大小
    plt.bar(range(3), [lv_four, lv_five, lv_six], width=0.4, alpha=0.8, color='skyblue')
    #left:x轴的位置序列,一般采用arange函数产生一个序列;
    #height:y轴的数值序列,也就是柱形图的高度,一般就是我们需要展示的数据;
    #alpha:透明度
    #width:为柱形图的宽度,一般这是为0.8即可;
    #color或facecolor:柱形图填充的颜色;
    plt.xticks([index for index in range(3)], ['4', '5', '6'])
    plt.rcParams['font.sans-serif'] = ['SimHei']#正常显示中文
    plt.xlabel('会员等级')
    plt.ylabel('会员人数')
    plt.title('会员各级别人数学号:3041')
    plt.show()
    plt.close()

  5. 绘制会员年龄分布箱型图
    age = data['AGE'].dropna()
    age = age.astype('int64')
    #绘制会员年龄分布箱型图
    fig = plt.figure(figsize=(5,10))
    plt.boxplot(age, patch_artist=True, labels=['会员年龄'], boxprops={'facecolor': 'lightblue'}) #设置填充颜色
    plt.rcParams['font.sans-serif'] = ['SimHei']#正常显示中文
    plt.title('会员年龄分布箱型图学号:3041')
    #显示y坐标轴的底线
    plt.grid(axis='y')
    plt.show()
    plt.close()

  6. 绘制最后乘机至结束时长箱线图
    # 乘机信息类别
    lte = data['LAST_TO_END']
    fc = data['FLIGHT_COUNT']
    sks = data['SEG_KM_SUM']
    
    # 绘制最后乘机至结束时长箱线图
    fig = plt.figure(figsize = (5 ,8))
    plt.boxplot(lte, 
                patch_artist=True,
                labels = ['时长'],  # 设置x轴标题
                boxprops = {'facecolor':'lightblue'})  # 设置填充颜色
    plt.title('会员最后乘机至结束时长分布箱线图学号:3041')
    # 显示y坐标轴的底线
    plt.grid(axis='y')
    plt.show()
    plt.close

  7. 绘制客户飞行次数箱线图
    # 绘制客户飞行次数箱线图
    fig = plt.figure(figsize = (5 ,8))
    plt.boxplot(fc, 
                patch_artist=True,
                labels = ['飞行次数'],  # 设置x轴标题
                boxprops = {'facecolor':'lightblue'})  # 设置填充颜色
    plt.title('会员飞行次数分布箱线图学号:3041')
    # 显示y坐标轴的底线
    plt.grid(axis='y')
    plt.show()
    plt.close

  8. 绘制客户总飞行公里数箱线图
    # 绘制客户总飞行公里数箱线图
    fig = plt.figure(figsize = (5 ,10))
    plt.boxplot(sks, 
                patch_artist=True,
                labels = ['总飞行公里数'],  # 设置x轴标题
                boxprops = {'facecolor':'lightblue'})  # 设置填充颜色
    plt.title('客户总飞行公里数箱线图学号:3041')
    # 显示y坐标轴的底线
    plt.grid(axis='y')
    plt.show()
    plt.close

  9. 绘制会员兑换积分次数直方图
    # 积分信息类别
    # 提取会员积分兑换次数
    ec = data['EXCHANGE_COUNT']
    # 绘制会员兑换积分次数直方图
    fig = plt.figure(figsize = (8 ,5))  # 设置画布大小
    plt.hist(ec, bins=5, color='#0504aa')
    plt.xlabel('兑换次数')
    plt.ylabel('会员人数')
    plt.title('会员兑换积分次数分布直方图学号:3041')
    plt.show()
    plt.close

  10. 绘制会员总累计积分箱线图
    # 提取会员总累计积分
    ps = data['Points_Sum']
    # 绘制会员总累计积分箱线图
    fig = plt.figure(figsize = (5 ,8))
    plt.boxplot(ps, 
                patch_artist=True,
                labels = ['总累计积分'],  # 设置x轴标题
                boxprops = {'facecolor':'lightblue'})  # 设置填充颜色
    plt.title('客户总累计积分箱线图学号:3041')
    # 显示y坐标轴的底线
    plt.grid(axis='y')
    plt.show()
    plt.close

  11. 绘制热力图
    #3.相关性分析
    #提取属性并合并为新的数据集
    import matplotlib.pyplot as plt
    import seaborn as sns
    data_corr = data.loc[:,['FFP_TIER', 'FLIGHT_COUNT', 'LAST_TO_END', 'SEG_KM_SUM', 'EXCHANGE_COUNT', 'Points_Sum']]
    
    age1 = data['AGE'].fillna(0)
    data_corr['AGE'] = age1.astype('int64')
    data_corr['ffp_year'] = ffp_year
    
    #计算相关性矩阵
    dt_corr = data_corr.corr(method='pearson')
    print('相关性矩阵为:\n', dt_corr)
    
    #绘制热力图
    plt.subplots(figsize=(10, 10))  #设置画面大小
    ## data:数据 square:是否是正方形 vmax:最大值 vmin:最小值 robust:排除极端值影响
    sns.heatmap(dt_corr, annot=True, vmax=1, square=True, cmap=sns.cubehelix_palette(as_cmap=True))#annot为默认下没有数值,cmap为选择颜色默认为红色,linewidth为间隔线
    plt.rcParams['font.sans-serif'] = ['SimHei']#正常显示中文
    plt.rcParams['axes.unicode_minus'] = False #正常显示负号
    plt.title('相关性热力图学号:3041')
    plt.show()
    plt.close()
    相关性矩阵为:
                     FFP_TIER  FLIGHT_COUNT  LAST_TO_END  SEG_KM_SUM  \
    FFP_TIER        1.000000      0.582447    -0.206313    0.522350   
    FLIGHT_COUNT    0.582447      1.000000    -0.404999    0.850411   
    LAST_TO_END    -0.206313     -0.404999     1.000000   -0.369509   
    SEG_KM_SUM      0.522350      0.850411    -0.369509    1.000000   
    EXCHANGE_COUNT  0.342355      0.502501    -0.169717    0.507819   
    Points_Sum      0.559249      0.747092    -0.292027    0.853014   
    AGE             0.076245      0.075309    -0.027654    0.087285   
    ffp_year       -0.116510     -0.188181     0.117913   -0.171508   
    
                    EXCHANGE_COUNT  Points_Sum       AGE  ffp_year  
    FFP_TIER              0.342355    0.559249  0.076245 -0.116510  
    FLIGHT_COUNT          0.502501    0.747092  0.075309 -0.188181  
    LAST_TO_END          -0.169717   -0.292027 -0.027654  0.117913  
    SEG_KM_SUM            0.507819    0.853014  0.087285 -0.171508  
    EXCHANGE_COUNT        1.000000    0.578581  0.032760 -0.216610  
    Points_Sum            0.578581    1.000000  0.074887 -0.163431  
    AGE                   0.032760    0.074887  1.000000 -0.242579  
    ffp_year             -0.216610   -0.163431 -0.242579  1.000000  
  12. 聚类绘制雷达图
    #4.数据预处理
    from sklearn.preprocessing import StandardScaler
    from sklearn.cluster import KMeans
    import numpy as np
    print('原始数据的形状为:\n', data.shape)
    #去除票价为空的记录
    data_notnull = data.loc[data['SUM_YR_1'].notnull() & data['SUM_YR_2'].notnull(), :]
    print('删除缺失记录后数据的形状为:\n', data_notnull.shape)
    #只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录
    index1 = data_notnull['SUM_YR_1'] != 0
    index2 = data_notnull['SUM_YR_2'] != 0
    index3 = (data_notnull['SEG_KM_SUM'] > 0) & (data_notnull['avg_discount'] != 0)
    index4 = data_notnull['AGE'] > 100  #去除年龄大于100的记录
    data_clean = data_notnull[(index1 | index2) & index3 & ~index4]
    print('清洗后数据的形状为:\n', data_clean.shape)
    
    #属性选择
    #选取需求属性
    data_selection = data_clean[['FFP_DATE', 'LOAD_TIME', 'LAST_TO_END', 'FLIGHT_COUNT', 'SEG_KM_SUM', 'avg_discount']]
    print('筛选的属性前5行为:\n', data_selection)
    #构造属性L
    L = pd.to_datetime(data_selection['LOAD_TIME']) - pd.to_datetime(data_selection['FFP_DATE'])
    L = L.astype('str').str.split().str[0]
    L = L.astype('int')/30
    #合并属性
    data_features = pd.concat([L, data_selection.iloc[:,2:]], axis=1)
    print('构建的LRFMC属性前5行为:\n', data_features.head())
    #数据标准化
    data_standar = StandardScaler().fit_transform(data_features)
    print('标准化后LRFMC 5个属性为:\n', data_standar[:5,:])
    
    #模型构建
    k = 5  #确定聚类中心数
    #构建模型,随机种子设为123
    kmeans_model = KMeans(n_clusters=k,random_state=123)
    fit_kmeans = kmeans_model.fit(data_standar)  #模型训练
    #查看聚类结果
    kmeans_cc = kmeans_model.cluster_centers_  #聚类中心
    print('各类聚类中心为:\n', kmeans_cc)
    kmeans_labels = kmeans_model.labels_  #样本的类别标签
    print('各样本的类别标签为:\n', kmeans_labels)
    r1 = pd.Series(kmeans_model.labels_).value_counts()  #统计不同类别样本的数目
    print('最终每个类别的数目为:\n', r1)
    #输出聚类分群的结果
    cluster_center = pd.DataFrame(kmeans_model.cluster_centers_, columns=['ZL', 'ZR', 'ZF', 'ZM', 'ZC'])  #将聚类中心放在数据框中
    print(cluster_center)
    cluster_center.index = pd.DataFrame(kmeans_model.labels_).drop_duplicates().iloc[:,0]  #将样本类别作为数据框索引
    print(cluster_center)
    print(cluster_center.index)
    print(pd.DataFrame(kmeans_model.labels_).drop_duplicates().iloc[:,0])
    
    #客户价值分析
    #客户分群雷达图
    labels = ['ZL', 'ZR', 'ZF', 'ZM', 'ZC']
    legen = ['客户群' + str(i + 1) for i in cluster_center.index]
    lstype = ['-', '--', (0, (3, 5, 1, 5, 1, 5)), ':', '-.']
    kinds = list(cluster_center.iloc[:,0])
    #由于雷达图要保证数据闭合,因此要添加L列,并转换为np.ndarray
    cluster_center = pd.concat([cluster_center, cluster_center[['ZL']]], axis=1)
    centers = np.array(cluster_center.iloc[:, 0:])
    
    #分割圆周长,并让其闭合
    n = len(labels)
    angle = np.linspace(0, 2 * np.pi, n, endpoint=False)
    angle = np.concatenate((angle, [angle[0]]))
    labels=np.concatenate((labels,[labels[0]]))
    #绘图
    fig = plt.figure(figsize=(8, 6))
    ax = fig.add_subplot(111, polar=True)  #以极坐标的形式绘制图形
    #画线
    for i in range(len(kinds)):
        ax.plot(angle, centers[i], linestyle=lstype[i], linewidth=2, label=kinds[i])
    #添加属性标签
    ax.set_thetagrids(angle * 180 / np.pi, labels)
    plt.rcParams['font.sans-serif'] = ['SimHei']#正常显示中文
    plt.title('客户特征分析雷达图学号:3041')
    plt.legend(legen)
    plt.show()
    plt.close

  13.  判断一个客户是,已流失,准流失,未流失的客户
    #判断一个客户是,已流失,准流失,未流失的客户
    import numpy as np
    import pandas as pd
    datafile='D:/人工智能&软件工程/数据挖掘与分析/data/air_data.csv'
    cleanedfile='D:/人工智能&软件工程/数据挖掘与分析/tmp/data_cleaned学号:3041.csv'
    airline_data=pd.read_csv(datafile,encoding='utf-8')
    print('原始数据的形状为:',airline_data.shape)
    airline_notnull=airline_data.loc[airline_data['SUM_YR_1'].notnull()&airline_data['SUM_YR_2'].notnull(),:]
    print('删除缺失记录后数据的形状为:\n',airline_notnull.shape)
    
    airline_data['单位里程票价'] = (airline_data['SUM_YR_1'] + airline_data['SUM_YR_2'])/airline_data['SEG_KM_SUM']
    airline_data['单位里程积分'] = (airline_data['P1Y_BP_SUM'] + airline_data['L1Y_BP_SUM'])/airline_data['SEG_KM_SUM']
    airline_data['飞行次数比例'] = airline_data['L1Y_Flight_Count'] / airline_data['P1Y_Flight_Count'] 
    airline_data = airline_data[airline_data['FLIGHT_COUNT'] > 6]
    airline_data = airline_data[['FFP_TIER','飞行次数比例','AVG_INTERVAL',
    'avg_discount','EXCHANGE_COUNT','Eli_Add_Point_Sum','单位里程票价','单位里程积分']]
    airline_data.to_csv(cleanedfile,index=None)
    
    input_file = 'D:/人工智能&软件工程/数据挖掘与分析/tmp/data_cleaned学号:3041.csv'
    output_file = 'D:/人工智能&软件工程/数据挖掘与分析/tmp/data_cleaned1学号:3041.csv'
    data = pd.read_csv(input_file,encoding='utf-8')
    data['客户类型'] = None
    for i in range(len(data)):
        if data['飞行次数比例'][i] < 0.5:
            data['客户类型'][i] = '已流失' 
        if (data['飞行次数比例'][i] >= 0.5) & (data['飞行次数比例'][i] < 0.9) :
            data['客户类型'][i] = '准流失' 
        if data['飞行次数比例'][i] >= 0.9:
            data['客户类型'][i] = '未流失' 
    data.to_csv(output_file,index=None)
    print('筛选的属性前5行为:\n',data.head()
    原始数据的形状为: (62988, 44)
    删除缺失记录后数据的形状为:
     (62299, 44)
    筛选的属性前5行为:
        FFP_TIER    飞行次数比例  AVG_INTERVAL  avg_discount  EXCHANGE_COUNT  \
    0         6  1.038835      3.483254      0.961639              34   
    1         6  1.058824      5.194245      1.252314              29   
    2         6  1.076923      5.298507      1.254676              20   
    3         5  0.769231     27.863636      1.090870              11   
    4         6  1.140845      4.788079      0.970658              27   
    
       Eli_Add_Point_Sum    单位里程票价    单位里程积分 客户类型  
    0             114452  0.815798  0.870145  未流失  
    1              53288  1.154043  1.234277  未流失  
    2              55202  1.158217  1.237731  未流失  
    3              34890  0.859648  1.198972  准流失  
    4              64969  0.823617  0.883573  未流失  

posted @ 2023-03-12 21:49  Binnie  阅读(77)  评论(0编辑  收藏  举报