我的这个项目放在百度网盘了,你可以提取。数据表都有。
链接:https://pan.baidu.com/s/1il9Uzs7xlcEkssIzeiZpfA
提取码:ys9e
一、对于数据的抽取
#1、数据抽取
import pandas as pd
datafile = './air_data.csv' # 航空原始数据路径
data = pd.read_csv(datafile, encoding = 'utf-8') #读取原始数据,指定UTF-8编码
二、数据探索分析
#2、数据探索分析
import pandas as pd
datafile= './air_data.csv' #航空原始数据,第一行为属性标签
resultfile = './explore.xls' #数据探索结果表
data = pd.read_csv(datafile, encoding = 'utf-8') #读取原始数据,指定UTF-8编码
explore = data.describe(percentiles = [], include = 'all').T #包括对数据的基本描述,percentiles参数是指定计算多少的分位数表(如1/4分位数、中位数等);T是转置,转置后更方便查阅
explore['null'] = len(data)-explore['count'] #describe()函数自动计算非空值数,需要手动计算空值数
explore = explore[['null', 'max', 'min']]
explore.columns = [u'空值数', u'最大值', u'最小值'] #表头重命名
explore.to_excel(resultfile) #导出结果
三、对于数据的清洗
import pandas as pd
datafile = './air_data.csv' # 航空原始数据路径
cleanedfile = './data_cleaned.csv' # 数据清洗后保存的文件路径
#对数据的清洗
def data_cleansing(datafile,cleanedfile):
# 读取数据
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('删除缺失记录后数据的形状为:',airline_notnull.shape)
# 只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录。
index1 = airline_notnull['SUM_YR_1'] != 0
index2 = airline_notnull['SUM_YR_2'] != 0
# 保留平均折扣率不为0且总飞行公里数大于0的记录。
index3 = (airline_notnull['SEG_KM_SUM']> 0) & (airline_notnull['avg_discount'] != 0)
index4 = airline_notnull['AGE'] > 100 # 去除年龄大于100的记录
airline = airline_notnull[(index1 | index2) & index3 & ~index4]
print('数据清洗后数据的形状为:',airline.shape)
airline.to_csv(cleanedfile,index=False, encoding='utf_8_sig') # 保存清洗后的数据
if __name__=='__main__':
data_cleansing(datafile,cleanedfile)
运行结果:
四、标准化后LRFMC
import pandas as pd
from sklearn.preprocessing import StandardScaler
datafile = './air_data.csv' # 航空原始数据路径
cleanedfile = './data_cleaned.csv' # 数据清洗后保存的文件路径
inputfile = '../tmp/zscoreddata.xls' #待聚类的数据文件
def data_extraction(cleanedfile, inputfile):
data = pd.read_csv(cleanedfile, encoding='utf-8')
# 入会时间 、观察窗口结束时间 最后一次飞行至结束的时长 飞行次数 飞行里程 折扣系数
data = data[['FFP_DATE', 'LOAD_TIME', 'LAST_TO_END', 'FLIGHT_COUNT', 'SEG_KM_SUM', 'avg_discount']]
# print(data)
# print("data 的shape:", data.shape)
# print("data columns:", data.columns)
# L、R、F、M和C五个特征的数据
# 求取L 会员人会时间距观测窗口结束的月数=观测窗口的结束时间一人会时间[单位:月]
# 计算结束时间和入会时间的差值
# L= LOAD_TIME—FFP_DATE/30
# 转换为时间格式
date = pd.to_datetime(data['LOAD_TIME']) - pd.to_datetime(data['FFP_DATE'])
# 取出其天数
date_list = [tmp.days for tmp in date]
data["date_list"] = date_list
data["L"] = data["date_list"] / 30
## 求 R 客户最近一次乘坐公司飞机距观测窗口结束的月数=最后一次乘机时间至观察窗口末端时长[单位:月]
# R= LAST_TO_END/30
data['R'] = data['LAST_TO_END'] / 30
# F 客户在观测窗口内乘坐公司飞机的次数=观测窗口的飞行次数[单位:次]
# F = FLIGHT_COUNT
data['F'] = data['FLIGHT_COUNT']
# M 客户在观测时间内在公司累计的飞行里程=观测窗口的总飞行公里数[单位:公里]
# M= SEG_KM_SUM
data['M'] = data['SEG_KM_SUM']
# C 客户在观测时间内乘坐舱位所对应的折扣系数的平均值=平均折扣率[单位:无]
# C= AVG_DISCOUNT
data['C'] = data['avg_discount']
# 只提取5个指标的数据
data = data.iloc[:, -5:]
# print(data)
# 标准化数据
# 调用标准差标准化
# def stand_sca(data):
# """
# 标准差标准化 x-u/a
# :param data: 数据
# :return: 标准化后的数据
# """
# data=(data-data.mean()/data.std())
# return data
# data = stand_sca(data)
# print("标准化之后的数据", data)
# 数据标准化
# 计算出数据的均值和方差
data = StandardScaler().fit_transform(data)
# np.savez('../tmp/airline_scale.npz', data)
print('标准化后LRFMC五个属性为:\n', data[:5, :])
# 数据写入
da = pd.DataFrame(data, columns=['L', 'R', 'F', 'M', 'C'])
print(da)
da.to_excel(inputfile, index=False, encoding='utf_8_sig')
if __name__=='__main__':
data_extraction(cleanedfile, inputfile)
运行结果:
五、客户特征分析雷达图
def show_res(cluster_center):
'''
:param center: 聚类中心
:param data: 5列航空数据
:return:
'''
# 客户分群雷达图
labels = ['L', 'R', 'F', 'M', 'C']
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[['L']]], 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]]))
# 绘图
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True) # 以极坐标的形式绘制图形
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 画线
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.title('客户特征分析雷达图')
plt.legend(legen)
plt.show()
plt.close
完整代码:
# 处理缺失值与异常值
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
datafile = './air_data.csv' # 航空原始数据路径
cleanedfile = './data_cleaned.csv' # 数据清洗后保存的文件路径
inputfile = './zscoreddata.xls' #待聚类的数据文件
outfile = './zscoreddata_1.xls' #聚类后的数据文件
def data_cleansing(datafile,cleanedfile):
# 读取数据
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('删除缺失记录后数据的形状为:',airline_notnull.shape)
# 只保留票价非零的,或者平均折扣率不为0且总飞行公里数大于0的记录。
index1 = airline_notnull['SUM_YR_1'] != 0
index2 = airline_notnull['SUM_YR_2'] != 0
# 保留平均折扣率不为0且总飞行公里数大于0的记录。
index3 = (airline_notnull['SEG_KM_SUM']> 0) & (airline_notnull['avg_discount'] != 0)
index4 = airline_notnull['AGE'] > 100 # 去除年龄大于100的记录
airline = airline_notnull[(index1 | index2) & index3 & ~index4]
print('数据清洗后数据的形状为:',airline.shape)
airline.to_csv(cleanedfile,index=False, encoding='utf_8_sig') # 保存清洗后的数据
def data_extraction(cleanedfile,inputfile):
data=pd.read_csv(cleanedfile,encoding='utf-8')
# 入会时间 、观察窗口结束时间 最后一次飞行至结束的时长 飞行次数 飞行里程 折扣系数
data = data[['FFP_DATE', 'LOAD_TIME', 'LAST_TO_END', 'FLIGHT_COUNT', 'SEG_KM_SUM', 'avg_discount']]
# print(data)
# print("data 的shape:", data.shape)
# print("data columns:", data.columns)
# L、R、F、M和C五个特征的数据
# 求取L 会员人会时间距观测窗口结束的月数=观测窗口的结束时间一人会时间[单位:月]
# 计算结束时间和入会时间的差值
# L= LOAD_TIME—FFP_DATE/30
#转换为时间格式
date=pd.to_datetime(data['LOAD_TIME'])-pd.to_datetime(data['FFP_DATE'])
# 取出其天数
date_list = [tmp.days for tmp in date]
data["date_list"] = date_list
data["L"] = data["date_list"] / 30
## 求 R 客户最近一次乘坐公司飞机距观测窗口结束的月数=最后一次乘机时间至观察窗口末端时长[单位:月]
# R= LAST_TO_END/30
data['R']=data['LAST_TO_END']/30
# F 客户在观测窗口内乘坐公司飞机的次数=观测窗口的飞行次数[单位:次]
# F = FLIGHT_COUNT
data['F']=data['FLIGHT_COUNT']
# M 客户在观测时间内在公司累计的飞行里程=观测窗口的总飞行公里数[单位:公里]
# M= SEG_KM_SUM
data['M']=data['SEG_KM_SUM']
# C 客户在观测时间内乘坐舱位所对应的折扣系数的平均值=平均折扣率[单位:无]
# C= AVG_DISCOUNT
data['C']=data['avg_discount']
# 只提取5个指标的数据
data=data.iloc[:,-5:]
# print(data)
# 标准化数据
# 调用标准差标准化
# def stand_sca(data):
# """
# 标准差标准化 x-u/a
# :param data: 数据
# :return: 标准化后的数据
# """
# data=(data-data.mean()/data.std())
# return data
# data = stand_sca(data)
# print("标准化之后的数据", data)
# 数据标准化
# 计算出数据的均值和方差
data = StandardScaler().fit_transform(data)
# np.savez('../tmp/airline_scale.npz', data)
print('标准化后LRFMC五个属性为:\n', data[:5, :])
#数据写入
da=pd.DataFrame(data,columns=['L', 'R', 'F', 'M', 'C'])
print(da)
da.to_excel(inputfile,index=False, encoding='utf_8_sig')
def show_res(cluster_center):
'''
:param center: 聚类中心
:param data: 5列航空数据
:return:
'''
# 客户分群雷达图
labels = ['L', 'R', 'F', 'M', 'C']
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[['L']]], 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]]))
# 绘图
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, polar=True) # 以极坐标的形式绘制图形
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 画线
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.title('客户特征分析雷达图')
plt.legend(legen)
plt.show()
plt.close
if __name__=='__main__':
data_extraction(cleanedfile,inputfile)
K=5 #需要聚类的级别数
#进行K-means聚类
#确认聚类的类别
data=pd.read_excel(inputfile,encoding='utf-8',)
print(data.head())
# 构建模型,随机种子设为123
km=KMeans(n_clusters = K,n_jobs=4,random_state=123)
km.fit(data) #训练数据
y_predict = km.predict(data) #进行预测
# # #获取聚类中心
center=km.cluster_centers_
print('聚类中心为:',center)
print('预测值:',y_predict)
kmeans_labels=km.labels_ #样本的类别标签
print('各个样本的类别标签为:\n',kmeans_labels)
r1=pd.Series(km.labels_).value_counts() #统计不同类别样本的数目
print('最终每个类别的数目为:\n',r1) #输出聚类分群的结果
# 将聚类中心放在数据框中
cluster_center=pd.DataFrame(km.cluster_centers_,
columns=['L','R','F','M','C'])
# 将聚类中心放在数据框中
cluster_center.index=pd.DataFrame(km.labels_).drop_duplicates().iloc[:,0]
# 将样本类别作为数据框索引
# print('111111111111111111111111111111111')
# print(cluster_center)
# cluster_center.to_excel(outfile,index=False,encoding='utf_8_sig')
show_res(cluster_center)
运行结果:
文章评论