1 import pandas as pd 2 import numpy as np 3 from sklearn.cluster import KMeans 4 import matplotlib.pyplot as plt 5 6 7 def stand_sca(data): 8 """ 9 标准差标准化 10 :param data:原数据 11 :return: 标准差之后的数据 12 """ 13 data = (data - data.mean()) / data.std() 14 15 return data 16 17 18 def box_analysis(data): 19 """ 20 箱线图分析去除异常值 21 :param data: 原数据---series 22 :return: bool数组 23 """ 24 # 上四分位数 25 qu = data.quantile(q=0.75) 26 # 下四分位数 27 ql = data.quantile(q=0.25) 28 # 计算四分位间距 29 iqr = qu - ql 30 31 # 上限 32 up = qu + 1.5 * iqr 33 # 下限 34 low = ql - 1.5 * iqr 35 36 bool_index = (data < up) & (data > low) 37 38 return bool_index 39 40 41 # 1、了解航空公司现状以及 航空用户的价值 42 # 6w+ 样本 44个特征 ----> LRFMC 43 # 2、数据处理 44 # (1)缺失值处理 45 # 删除法 46 # (2) 筛选相关特征---构建最终的特征 47 # LRFMC <----筛选出能够构建这5个特征的相关特征 48 # (3)异常值处理 49 # 3sigma 原则 或者 box_analysis 50 # (4)标准化处理 51 # 标准差标准化 52 # 3、k-means实现航空用户的聚类 53 # sklearn 54 # 4、结果展示 55 # 绘制雷达图 56 # 5、输出结论 57 # 营销策略 58 59 def build_data(): 60 """ 61 构建原始数据 62 :return: 原始数据 63 """ 64 # 1、加载数据 65 air_data = pd.read_csv("./air_data.csv", encoding="ansi") 66 # print("air_data:\n", air_data) 67 # print("air_data 的列索引名称:\n", air_data.columns) 68 69 return air_data 70 71 72 def deal_data(air_data): 73 """ 74 数据处理 75 :param air_data:原始数据 76 :return: 数据处理之后的结果 77 """ 78 # 2、数据清洗 79 # 缺失值、异常值 80 # 检测缺失值 81 res_null = pd.isnull(air_data).sum() 82 # print("缺失值检测结果:", res_null) 83 84 # 处理缺失值 85 # (1)丢弃票价为空的记录 # SUM_YR_1 SUM_YR_2两列 86 # ----可以理解保留票价不为空 87 bool_index_1 = air_data.loc[:, "SUM_YR_1"].notnull() 88 bool_index_2 = air_data.loc[:, "SUM_YR_2"].notnull() 89 # 个人认为 只有两列票价都不为空,票价才不为空 90 bool_index = bool_index_1 & bool_index_2 91 air_data = air_data.loc[bool_index, :] 92 # (2)丢弃票价为0,折扣不为0,飞行里程 > 0 的数据--->丢弃航空公司没有盈利的数据 93 # 保留盈利的数据 94 # 保留票价 > 0,折扣 > 0,飞行里程 > 0 95 # 个人认为只要有一列票价>0,票价就>0 96 bool_id_1 = air_data.loc[:, "SUM_YR_1"] > 0 97 bool_id_2 = air_data.loc[:, "SUM_YR_2"] > 0 98 99 # 折扣> 0 100 bool_id_3 = air_data.loc[:, "avg_discount"] > 0 101 102 # 飞行里程>0 103 bool_id_4 = air_data.loc[:, "SEG_KM_SUM"] > 0 104 105 bool_id = (bool_id_1 | bool_id_2) & bool_id_3 & bool_id_4 106 107 air_data = air_data.loc[bool_id, :] 108 109 res_null = pd.isnull(air_data).sum() 110 # print("缺失值检测结果:", res_null) 111 112 # 先筛选特征 113 # LRFMC 114 # 筛选 入会时间、窗口结束时间、最后乘坐飞机距离窗口结束的时长,乘坐飞机次数、飞行里程、折扣系数 115 air_data = air_data.loc[:, ["FFP_DATE", "LOAD_TIME", "LAST_TO_END", "FLIGHT_COUNT", "SEG_KM_SUM", "avg_discount"]] 116 117 # 构建LRFMC五个特征 118 air_data.loc[:, "FFP_DATE"] = pd.to_datetime(air_data.loc[:, "FFP_DATE"]) 119 air_data.loc[:, "LOAD_TIME"] = pd.to_datetime(air_data.loc[:, "LOAD_TIME"]) 120 # 获取时间差--单位是day 121 air_data.loc[:, "L_days"] = air_data.loc[:, "LOAD_TIME"] - air_data.loc[:, "FFP_DATE"] 122 # 获取相差天数 的数值 123 air_data.loc[:, "L_days"] = [i.days for i in air_data.loc[:, "L_days"]] 124 # 获取具体的月数--即L 125 air_data.loc[:, "L"] = np.ceil(air_data.loc[:, "L_days"] / 30) 126 # print(air_data.loc[:, "L"]) 127 # 构建R --- LAST_TO_END 这个时长应该是天数 128 # print(air_data.loc[:, "LAST_TO_END"]) 129 air_data.loc[:, "R"] = np.ceil(air_data.loc[:, "LAST_TO_END"] / 30) 130 # print("air_data.loc[:, "R"]:\n",air_data.loc[:, "R"]) 131 132 air_data.loc[:, "F"] = air_data.loc[:, "FLIGHT_COUNT"] 133 134 air_data.loc[:, "M"] = air_data.loc[:, "SEG_KM_SUM"] 135 136 air_data.loc[:, "C"] = air_data.loc[:, "avg_discount"] 137 138 air_data = air_data.iloc[:, -5:] 139 # print("最终的数据:\n", air_data) 140 141 # 异常值处理 142 for column in air_data.columns: 143 bool_ = box_analysis(air_data.loc[:, column]) 144 air_data = air_data.loc[bool_, :] 145 146 # 标准化数据 147 air_data = stand_sca(air_data) 148 149 print("标准化之后的数据:\n", air_data) 150 151 return air_data 152 153 154 def km_fit(air_data, k): 155 """ 156 k-means训练数据,并进行用户聚类 157 :param air_data: 数据 158 :param k: 聚类的类别数目 159 :return: 160 """ 161 # 1、创建算法实例 162 km = KMeans(n_clusters=k) 163 # 2、训练数据 164 km.fit(air_data) 165 # 3、预测 166 y_predict = km.predict(air_data) 167 168 # 获取聚类中心 169 center = km.cluster_centers_ 170 171 return y_predict, center 172 173 174 def show_res(center, feature_num): 175 """ 176 绘制雷达图 177 :param center:聚类中心 178 :param feature_num: 特征的数量 179 :return: 180 """ 181 # 1、创建画布 182 # 绘制雷达图 需要用到极坐标 183 fig = plt.figure() 184 # 修改RC参数,来让其支持中文 185 plt.rcParams['font.sans-serif'] = 'SimHei' 186 plt.rcParams['axes.unicode_minus'] = False 187 # polar 开启极坐标 188 fig.add_subplot(1, 1, 1, polar=True) 189 # 2、绘图 190 # 准备数据 191 # 准备角度数据 192 angle = np.linspace(start=0, stop=2 * np.pi, num=feature_num, endpoint=False) 193 print(angle) 194 # 闭合角度 195 angle = np.concatenate((angle, [angle[0]])) 196 # print(angle) 197 for i in range(center.shape[0]): 198 # print(center[i, 0]) 199 # 闭合数据 200 data = np.concatenate((center[i, :],[center[i, 0]])) 201 plt.polar(angle, data) 202 203 # 设置刻度 204 plt.xticks(angle[:-1],["L","R","F","M","C"]) 205 206 # 增加图例 207 plt.legend(["第一类用户","第二类用户","第三类用户","第四类用户","第五类用户"]) 208 # 保存图片 209 plt.savefig("./航空用户聚类分析结果雷达图展示.png") 210 # 3、展示 211 plt.show() 212 213 214 def main(): 215 """ 216 主函数 217 :return: 218 """ 219 # 1、构建原始数据 220 air_data = build_data() 221 # 2、数据处理 222 air_data = deal_data(air_data) 223 # 3、构建聚类模型进行用户聚类 224 # 确定聚类的类别数目 225 k = 5 226 y_predict, center = km_fit(air_data, k) 227 print("预测值为:\n", y_predict) 228 print("聚类中心为:\n", center) 229 230 # 4、结果展示 231 show_res(center, center.shape[1]) 232 233 234 if __name__ == '__main__': 235 main()