"""
了解航空现状
了解 40个特征--每个特征的含义
观察窗口---2012-04-01 ----2014-03-31,我们给定的数据 就是观察窗口内的数据
# 丢弃票价为空的记录-----保留票价不为空的记录
# 丢弃票价为0 ,折扣不为0,飞行里程大于0 的数据 -----没花钱,而且还乘坐飞机了
# ===》保留票价>0 ,折扣不为0 ,飞行里程大于0 的数据 ---真真正正花钱坐飞机
# 筛选特征的时候---去 筛选出能够与LRFMC 相关的特征出来
# 构建特征的时候 需要构建 ---LRFMC五个特征
# 进行异常值处理 ---箱线图分析/3sigma
#标准化数据 --->自定义的 也可以用sklearn 的
# 数据已经就位
# km聚类---聚为5类,聚类中心可以拿到了
# 常规的 散点图不适合这类结果
# 结果展示---雷达图
# 分析--给出建议
"""
import pandas as pd
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import numpy as np
def box_analysis(data):
"""
进行箱线图分析,剔除异常值
:param data: series
:return: bool数组
"""
qu = data.quantile(0.75)
# print(qu)
ql = data.quantile(0.25)
# print(ql)
iqr = qu - ql
# 上限
up = qu + 1.5 * iqr
# 下限
low = ql - 1.5 * iqr
# 进行比较运算
bool_id_1 = data <= up
bool_id_2 = data >= low
bool_num = bool_id_1 & bool_id_2
return bool_num
# 1、加载数据
air_data = pd.read_csv("./air_data.csv", encoding='ansi')
print("air_data:\n", air_data)
print("air_data 的形状:\n", air_data.shape)
print("air_data 列索引:\n", air_data.columns)
# 2、缺失值处理
# 丢弃票价为空的记录-----保留票价不为空的记录
bool_id_1 = air_data.loc[:, 'SUM_YR_1'].notnull() # 不为空的 为T,空的为F
bool_id_2 = air_data.loc[:, 'SUM_YR_2'].notnull()
bool_id = bool_id_1 & bool_id_2
air_data = air_data.loc[bool_id, :]
print("*" * 80)
print("丢弃票价为空的记录之后的结果:\n", air_data.shape)
# 丢弃票价为0 ,折扣不为0,飞行里程大于0 的数据 -----没花钱,而且还乘坐飞机了
# ===》保留票价>0 ,折扣不为0 ,飞行里程大于0 的数据 ---真真正正花钱坐飞机
bool_num_1 = air_data.loc[:, 'SUM_YR_1'] > 0
bool_num_2 = air_data.loc[:, 'SUM_YR_2'] > 0
bool_num_3 = air_data.loc[:, 'avg_discount'] > 0
bool_num_4 = air_data.loc[:, 'SEG_KM_SUM'] > 0
bool_num = (bool_num_1 | bool_num_2) & bool_num_3 & bool_num_4
air_data = air_data.loc[bool_num, :]
print("*" * 80)
print("丢弃票价为0 ,折扣不为0,飞行里程大于0 的数据之后的结果:\n", air_data.shape)
# 3、筛选特征
air_data = air_data.loc[:, ['FFP_DATE', 'LOAD_TIME', 'LAST_TO_END', 'FLIGHT_COUNT', 'SEG_KM_SUM', 'avg_discount']]
print("*" * 80)
print("筛选出有效特征之后的结果:\n", air_data)
# 4、构建LRFMC五个特征
# 先将数据转化为pandas默认支持的时间序列数据
# 构建L
air_data.loc[:, 'LOAD_TIME'] = pd.to_datetime(air_data.loc[:, 'LOAD_TIME'])
air_data.loc[:, 'FFP_DATE'] = pd.to_datetime(air_data.loc[:, 'FFP_DATE'])
air_data.loc[:, 'L_days'] = air_data.loc[:, 'LOAD_TIME'] - air_data.loc[:, 'FFP_DATE']
print("*" * 80)
air_data.loc[:, 'L_days'] = [i.days for i in air_data.loc[:, 'L_days']]
air_data.loc[:, 'L'] = air_data.loc[:, 'L_days'] / 30
# print("计算出的L_days结果:\n", air_data.loc[:, 'L_days'])
# print("*" * 80)
# print("计算出的L结果:\n", air_data.loc[:, 'L'])
# 构建R
print("*" * 80)
# 先将数据转化为pandas默认支持的时间序列数据
air_data.loc[:, 'R'] = air_data.loc[:, 'LAST_TO_END'] / 30
# 构建F
air_data.loc[:, 'F'] = air_data.loc[:, 'FLIGHT_COUNT']
# 构建 M
air_data.loc[:, 'M'] = air_data.loc[:, 'SEG_KM_SUM']
# 构建C
air_data.loc[:, 'C'] = air_data.loc[:, 'avg_discount']
# 取出LRFMC
data = air_data.iloc[:, -5:]
print("构建好特征之后的data:\n", data.shape)
print("*" * 80)
# 5\进行异常值处理
for i in range(len(data.columns)):
bool_index = box_analysis(data.iloc[:, i])
data = data.loc[bool_index, :]
print("处理完异常值之后的结果:\n", data.shape)
# 6、标准化处理
stand = StandardScaler()
x = stand.fit_transform(data)
print("*" * 80)
print("标准化之后的结果:\n", x)
# 7、进行聚类
k = 5
# 创建实例
km = KMeans(n_clusters=k)
# 训练数据
km.fit(x)
# 预测类别
y_predict = km.predict(x)
# 获取聚类中心
center = km.cluster_centers_
print("*" * 80)
print("聚类中心:\n", center)
print("预测标签值:\n", y_predict)
# 1、创建画布
plt.figure()
# 默认不支持中文,需要配置RC 参数
plt.rcParams['font.sans-serif']='SimHei'
# 设置字体之后不支持负号,需要去设置RC参数更改编码
plt.rcParams['axes.unicode_minus']=False
# 创建子图 polar=开启极坐标
plt.subplot(111, polar=True)
# 2、绘图
# 设计角度
datalength = 5
angle = np.linspace(0, 2 * np.pi, num=datalength,endpoint=False)
# 闭合角度
angle = np.concatenate((angle,[angle[0]]),axis=0)
# 循环闭合数据 并进行绘图
for i in range(k):
# 循环进行闭合数据
data = np.concatenate((center[i,:],[center[i,0]]))
# 每闭合一次数据,就进行绘制一次图形
plt.polar(angle,data)
print(angle)
# 设置刻度
labels = ["L","R","F","M","C"]
plt.xticks(angle,labels)
# 增加标题
plt.title("航空用户聚类分析")
#设置图例
plt.legend(["用户群体一","用户群体二","用户群体三","用户群体四","用户群体五"])
# 保存图片
plt.savefig("./航空用户聚类分析.png")
# 3、展示
plt.show()