python实现——综合类型数据挖掘任务(无监督的分类任务)

综合类型数据挖掘任务

航空公司客户价值分析。航空公司客户价值分析。航空公司客户价值分析。航空公司已积累了大量的会员档案信息和其乘坐航班记录(air_data.csv),以2014年3月31日为结束时间抽取两年内有乘机记录的所有客户的详细数据。利用聚类算法对客户数据进行群体划分,并根据客户群体LRFMC指标分析并给出各客户群体的类型。

数据共有62988条,每条数据具有44个特征。包含会员卡号、入会时间、性别、年龄、会员卡级别、工作地城市、工作地所在省份、工作地所在国家、观测窗口结束时间、观测窗口乘机积分、飞行公里数、飞行次数、飞行时间、乘机时间间隔、平均折扣率等特征。

3.1数据预处理

航空公司客户原始数据存在少量的缺失值和异常值,需要清洗后才能用于分析。票价为空值、票价最小值为0、折扣率最小值为0总飞行千米数大于0的记录。票价为空值的数据可能是由于不存在乘机记录造成的。其他的数据可能是由于客户乘坐0折机票或者积分兑换造成的。

字段

异常情况

SUM_YR_1

NaN

SUM_YR_2

NaN

avg_discount、SEG_KM_SUM

avg_discount=0&SEG_KM_SUM>0

SUM_YR_1、SUM_YR_2

同时为0

处理后的数据有62044条。

# 读取原始数据
data = pd.read_csv('air_data.csv')
# 清洗数据
# 将票价为空值的数据删除
data = data[~data['SUM_YR_1'].isnull() & ~data['SUM_YR_2'].isnull()]
# 将票价为0或折扣率为0但总飞行千米数大于0的记录删除
data = data[~((data['avg_discount'] == 0) & (data['SEG_KM_SUM'] > 0))]
# 将SUM_YR_1和SUM_YR_2同时为0的记录删除
data = data[~((data['SUM_YR_1'] == 0) & (data['SUM_YR_2'] == 0))]

 

 

3.2特征提取

由于原始数据的特征过多,不便直接用于客户价值分析,因此需要对特征进行筛选,根据LRFMC模型挑选出衡量客户价值的关键特征,分别是:

  • Length of Relationship: 客户关系时长,反映客户的活跃时长。
  • Recency: 最近消费时间间隔,反映当前的活跃状态。
  • Frequency: 客户消费频率,反映客户的忠诚度。
  • Mileage: 客户总飞行里程,反映客户对乘机的依赖性。
  • Coefficient of Discount: 客户所享受的平均折扣率,侧面反映客户价值高低。

特征

对应字段

L

LOAD_TIME与FFP_DATE之差

R

LAST_TO_END

F

FLIGHT_COUNT

M

SEG_KM_SUM

C

avg_discount

特征提取后的数据为下图所示:

# 假设你的数据框称为 df,包含了原始数据和对应的特征字段
df = data
# 计算 LRFMC 模型对应的特征
df['L'] = (pd.to_datetime(df['LOAD_TIME']) - pd.to_datetime(df['FFP_DATE'])).dt.days
df['R'] = df['LAST_TO_END']
df['F'] = df['FLIGHT_COUNT']
df['M'] = df['SEG_KM_SUM']
df['C'] = df['avg_discount']

from sklearn.preprocessing import StandardScaler

# 创建一个标准化器
scaler = StandardScaler()

# 假设你的数据框称为 df,包含了需要标准化的特征字段
features_to_scale = ['L', 'R', 'F', 'M', 'C']

# 对选择的特征进行均值方差标准化
df[features_to_scale] = scaler.fit_transform(df[features_to_scale])

print(df)

 

3.3数据标准化

对提取的数据进行均值方差标准化。

# 标准化数据
scaler = StandardScaler()
scaled_features = scaler.fit_transform(df2)
df_scaled = pd.DataFrame(scaled_features, columns=df2.columns)

 

3.4模型构建

本项目为聚类类型的任务,选择Kmeans对数据进行聚类,从而得到航空公司客户的类型分析结果。但要聚成多少类,很难断定。所以需要采用循环的方法,以聚类的个数作为循环变量(2到10),依次训练不同聚类个数的Kmeans模型,使用calinski_harabasz_score方法对各个Kmeans模型的结果进行评分。

# 创建一个空列表用于存放不同聚类数对应的评分
scores = []

# 设置循环,尝试不同的聚类个数
for n_clusters in range(2, 6):
    # 创建并训练Kmeans模型
    kmeans = KMeans(n_clusters=n_clusters, random_state=42)
    kmeans.fit(df_scaled)
    
    # 使用calinski_harabasz_score方法对模型进行评分
    score = calinski_harabasz_score(df_scaled, kmeans.labels_)
    scores.append(score)

# 打印各个聚类数对应的评分
for n_clusters, score in zip(range(2, 6), scores):
    print(f"Number of clusters: {n_clusters}, Calinski-Harabasz score: {score}")

 

 

# 可视化不同聚类数对应的评分
plt.figure(figsize=(10, 6))
plt.plot(range(2, 6), scores, marker='o')
plt.title('Calinski-Harabasz Score for Different Number of Clusters')
plt.xlabel('Number of clusters')
plt.ylabel('Calinski-Harabasz Score')
plt.show()

 

3.5模型训练

从上图中可以看出,聚类个数为2时模型评分最高,但仅将客户划分为2类会导致客户分类结果过于笼统,因此退而求其次,选择模型分数第二高的4作为聚类个数。

# 创建并训练最终的KMeans模型
final_kmeans = KMeans(n_clusters=4, random_state=42)
final_kmeans.fit(df_scaled)

# 将每个样本分配到对应的簇中
cluster_labels = final_kmeans.predict(df_scaled)

# 将簇标签添加到原始数据中
df2['cluster'] = cluster_labels

# 查看每个簇中样本的数量
cluster_counts = df2['cluster'].value_counts()
print(cluster_counts)

 

3.6结果分析

根据聚类结果绘制客户特征分析雷达图,根据雷达图显示的情况来对每个客户群的特征进行分析。

 

# 计算每个簇的平均特征值
cluster_means = df2.groupby('cluster').mean()

# 每个簇的特征名称
features = cluster_means.columns.tolist()

# 将第一个特征复制到列表末尾,以闭合雷达图
features.append(features[0])

# 绘制雷达图
plt.figure(figsize=(10, 8))
for cluster in range(4):
    values = cluster_means.iloc[cluster].values.tolist()
    values.append(values[0])
    angles = np.linspace(0, 2 * np.pi, len(features), endpoint=False).tolist()
    ax = plt.subplot(2, 2, cluster + 1, polar=True)
    ax.fill(angles, values, 'b', alpha=0.1)
    ax.plot(angles, values, linewidth=1.5, linestyle='solid', label=f'Cluster {cluster}')
    ax.fill(angles, values, alpha=0.25)
    ax.set_yticklabels([])
    ax.set_thetagrids(np.degrees(angles), labels=features)
    ax.set_title(f'Cluster {cluster}')

plt.show()

 

分析结果:

群体

类型

客户群体1

重要挽留客户

客户群体2

一般客户

客户群体3

低价值客户

客户群体4

重要保持客户

客户群体LRFMC指标分析:

群体

会员资历L

最近乘机R

乘机次数F

飞行里程M

平均折扣C

重要保持客户

★★★★

★★★★★

★★★★★

★★★★

重要发展客户

★★★

★★★★

★★

★★

★★★★★

重要挽留客户

★★★★★

★★★

★★★★

★★★★

★★★

一般客户

★★★★

★★

★★

低价值客户

★★

★★★★★

★★

客户群体特点及策略:

群体

特点及策略

重要保持客户

平均折扣率高(C↑),最近有乘机记录(R↓),乘机次数高(F↑)或里程高(M↑)

这类客户机票票价高,不在意机票折扣,经常乘机,是最理想的客户类型。公司应优先将资源投放到他们身上,维持这类客户的忠诚度。

重要发展客户

平均折扣率高(C↑),最近有乘机记录(R↓),乘机次数低(F↓)或里程低(M↓)

这类客户机票票价高,不在意机票折扣,最近有乘机记录,但总里程低,具有很大的发展潜力。公司应加强这类客户的满意度,使他们逐渐成为忠诚客户。

重要挽留客户

平均折扣率高(C↑),乘机次数高(F↑)或里程高(M↑),最近无乘机记录(R↑)

这类客户总里程高,但较长时间没有乘机,可能处于流失状态。公司应加强与这类客户的互动,召回用户,延长客户的生命周期。

一般客户

平均折扣率低(C↓),最近无乘机记录(R↑),乘机次数高(F↓)或里程高(M↓),入会时间短(L↓)

这类客户机票票价低,经常买折扣机票,最近无乘机记录,可能是趁着折扣而选择购买,对品牌无忠诚度。公司需要在资源支持的情况下强化对这类客户的联系。

低价值客户

平均折扣率低(C↓),最近无乘机记录(R↑),乘机次数高(F↓)或里程高(M↓),入会时间短(L↓)这类客户与一般客户类似,机票票价低,经常买折扣机票,最近无乘机记录,可能是趁着折扣而选择购买,对品牌无忠诚度。

完整代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import calinski_harabasz_score
from sklearn.preprocessing import StandardScaler
#%%
# 读取原始数据
data = pd.read_csv('air_data.csv')
# 清洗数据
# 将票价为空值的数据删除
data = data[~data['SUM_YR_1'].isnull() & ~data['SUM_YR_2'].isnull()]
# 将票价为0或折扣率为0但总飞行千米数大于0的记录删除
data = data[~((data['avg_discount'] == 0) & (data['SEG_KM_SUM'] > 0))]
# 将SUM_YR_1和SUM_YR_2同时为0的记录删除
data = data[~((data['SUM_YR_1'] == 0) & (data['SUM_YR_2'] == 0))]
#%%
# 假设你的数据框称为 df,包含了原始数据和对应的特征字段
df = data
# 计算 LRFMC 模型对应的特征
df['L'] = (pd.to_datetime(df['LOAD_TIME']) - pd.to_datetime(df['FFP_DATE'])).dt.days
df['R'] = df['LAST_TO_END']
df['F'] = df['FLIGHT_COUNT']
df['M'] = df['SEG_KM_SUM']
df['C'] = df['avg_discount']
#%%
# 创建一个标准化器
scaler = StandardScaler()
# 假设你的数据框称为 df,包含了需要标准化的特征字段
features_to_scale = ['L', 'R', 'F', 'M', 'C']
# 对选择的特征进行均值方差标准化
df[features_to_scale] = scaler.fit_transform(df[features_to_scale])
#%%
# 创建DataFrame
df2 = pd.DataFrame()
df2['L']=df['L']
df2['R']=df['R'] 
df2['F']=df['F'] 
df2['M']=df['M'] 
df2['C']=df['C']
#%%
# 标准化数据
scaler = StandardScaler()
scaled_features = scaler.fit_transform(df2)
df_scaled = pd.DataFrame(scaled_features, columns=df2.columns)
#%%
# 创建一个空列表用于存放不同聚类数对应的评分
scores = []
# 设置循环,尝试不同的聚类个数
for n_clusters in range(2, 15):
    # 创建并训练Kmeans模型
    kmeans = KMeans(n_clusters=n_clusters, random_state=42)
    kmeans.fit(df_scaled)
    # 使用calinski_harabasz_score方法对模型进行评分
    score = calinski_harabasz_score(df_scaled, kmeans.labels_)
    scores.append(score)
# 打印各个聚类数对应的评分
for n_clusters, score in zip(range(2, 15), scores):
    print(f"Number of clusters: {n_clusters}, Calinski-Harabasz score: {score}")
#%%
# 可视化不同聚类数对应的评分
plt.figure(figsize=(10, 6))
plt.plot(range(2, 15), scores, marker='o')
plt.title('Calinski-Harabasz Score for Different Number of Clusters')
plt.xlabel('Number of clusters')
plt.ylabel('Calinski-Harabasz Score')
plt.show()
#%%
# 创建并训练最终的KMeans模型
final_kmeans = KMeans(n_clusters=4, random_state=42)
final_kmeans.fit(df_scaled)
# 将每个样本分配到对应的簇中
cluster_labels = final_kmeans.predict(df_scaled)
# 将簇标签添加到原始数据中
df2['cluster'] = cluster_labels
# 查看每个簇中样本的数量
cluster_counts = df2['cluster'].value_counts()
print(cluster_counts)

#%%
# 计算每个簇的平均特征值
cluster_means = df2.groupby('cluster').mean()
# 每个簇的特征名称
features = cluster_means.columns.tolist()
# 将第一个特征复制到列表末尾,以闭合雷达图
features.append(features[0])
# 绘制雷达图
plt.figure(figsize=(10, 8))
for cluster in range(4):
    values = cluster_means.iloc[cluster].values.tolist()
    values.append(values[0])
    angles = np.linspace(0, 2 * np.pi, len(features), endpoint=False).tolist()
    ax = plt.subplot(2, 2, cluster+1, polar=True)
    ax.fill(angles, values, 'b', alpha=0.1)
    ax.plot(angles, values, linewidth=1.5, linestyle='solid', label=f'Cluster {cluster}')
    ax.fill(angles, values, alpha=0.25)
    ax.set_yticklabels([])
    ax.set_thetagrids(np.degrees(angles), labels=features)
    ax.set_title(f'Cluster {cluster}')
plt.show()
#%%
plt.figure(figsize=(10, 8))
# 创建一个极坐标子图
ax = plt.subplot(111, polar=True)
for cluster in range(4):
    values = cluster_means.iloc[cluster].values.tolist()
    values.append(values[0])
    angles = np.linspace(0, 2 * np.pi, len(features), endpoint=False).tolist() 
    # 绘制雷达图
    ax.fill(angles, values, alpha=0.1)
    ax.plot(angles, values, linewidth=1.5, linestyle='solid', label=f'Cluster {cluster}')
    ax.fill(angles, values, alpha=0.25)
# 隐藏雷达图的刻度和标签
ax.set_yticklabels([])
ax.set_thetagrids(np.degrees(angles), labels=features)
# 添加图例
plt.legend(loc='upper right')
plt.show()
#%%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/666757.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python使用动态代理的多元应用

Python作为一种功能强大且易于学习的编程语言,在网络编程领域具有广泛的应用。当Python与动态代理技术结合时,便开启了一扇通往更多可能性的大门。以下将深入探讨Python使用动态代理可以实现的多种应用。 首先,Python结合动态代理在网络爬虫…

WebRTC 各端的互联互通

WebRTC 各端的互联互通 WebRTC 各端的互联互通WebRTC Native 的核心一对一通信的时序图发起通话接收通话关闭通话 Android 端的实现iOS 端的实现各开发方案的比较参考 WebRTC 各端的互联互通 WebRTC Native 的核心 正如 WebRTC Web 端的核心是 RTCPeerConnection,…

自适应全屏滚动,实现swiper 全屏滚动效果与解决bug

原来是想复刻明日方舟的滚动代码,基于此进行开发 js实现网页全屏切换(平滑过渡),鼠标滚动切换_网页滚动条下滑和全屏切换是什么-CSDN博客 但是发现bug BUG 原因是只获取了一次高度 于是增加窗口监听, 但是发现拉伸…

C语言王国——杨氏矩阵

目录 1. 引言 2. 了解杨氏矩阵 3. 思路分析 4. 代码 5. 总结 1. 引言 最近在做二维数组的训练的时候发现了一个很有意思的题: 一看这不是杨氏矩阵嘛,接下来就由姜糖我带大家了解一下这个著名的矩阵。 2. 了解杨氏矩阵 通过查阅百度得知: …

电脑如何开启硬件虚拟化?这 2 种方法都可以使用

开启硬件虚拟化的方法 我们应该如何开启硬件虚拟化呢?下面就为大家总结了 2 种开启电脑硬件虚拟化的方法。 WinRE 启用 我们可以通过 Windows 恢复环境也就是 WinRE 在UEFI 或者 BIOS 上开启硬件虚拟化,大家可以按照下面的步骤进行操作。 首先打开设…

【Python】解决Python报错:AttributeError: ‘int‘ object has no attribute ‘xxx‘

🧑 博主简介:阿里巴巴嵌入式技术专家,深耕嵌入式人工智能领域,具备多年的嵌入式硬件产品研发管理经验。 📒 博客介绍:分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向…

Prometheus + Grafana + Alertmanager 系统监控

PrometheusGrafana 系统监控 1. 简介1.1 Prometheus 普罗 米修斯1.2 Grafana 2. 快速试用2.1 Prometheus 普罗 米修斯2.2 Prometheus 配置文件2.3 Grafana 2. 使用 Docker-Compose脚本部署监控服务3. Grafana 配置3.1 配置数据源 Prometheus3.2 使用模板ID 配置监控模板3.3 使用…

SpringBoot 单元测试 指定 环境

如上图所示,在配置窗口中添加--spring.profiles.activedev,就可以了。

【算法实战】每日一题:在后面的位置找到比当前元素第一个大的元素(非暴力,单调栈)

1. 数据结构-单调栈 单调栈是一种特殊的栈结构,它只允许栈内的元素保持单调性(单调递增或单调递减)。在实际应用中,单调栈常用于解决与单调性相关的算法问题,如找到下一个比当前元素大(或小)的…

与牢霍沟通——Linux操作系统原理

硬件层 计算机由何组成? 我们现在手中的计算机,无论配置如何,是笔记本还是台式,都由三部分构成: 输入设备:键盘,鼠标...中央处理器:cpu,显卡,磁盘...输出设…

在鲲鹏服务器上安装nginx

华为鲲鹏服务器采用华为自研cpu ARMv8架构,提供 Windows 和多个Linux 系统 常使用 CentOS 7.6 64bit with ARM Nginx 和 Apache 一样都是一种 Web 服务器。是基于 REST 架构风格,以统一资源描述符URI 或者统一资源定位符URL 作为沟通依据,通过 HTTP 协议…

Flink系列二:DataStream API中的Source,Transformation,Sink详解(^_^)

在上面篇文章中已经对flink进行了简单的介绍以及了解了Flink API 层级划分,这一章内容我们主要介绍DataStream API 流程图解: 一、DataStream API Source Flink 在流处理和批处理上的 source 大概有 4 类: (1)基于本…

【深度学习】安全帽检测,目标检测,yolov10算法,yolov10训练

文章目录 一、数据集二、yolov10介绍三、数据voc转换为yolo四、训练五、验证六、数据、模型、训练后的所有文件 寻求帮助请看这里: https://docs.qq.com/sheet/DUEdqZ2lmbmR6UVdU?tabBB08J2一、数据集 安全帽佩戴检测 数据集:https://github.com/njvi…

匿名函数(lambda)

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 匿名函数是指没有名字的函数,应用在需要一个函数,但是又不想费神去命名这个函数的场合。通常情况下,这样的函数只…

VRTK4.0学习——(二)

手柄绑定以及显示 1.导入CameraRigs.UnityXRPluginFramework 和 CameraRigs.TrackedAlias 预设,将CameraRigs.UnityXRPluginFramework拖入CameraRigs.TrackedAlias的Elements中即可,运行软件后即可看到手柄了 注:如果无法看到手柄&#xff…

鹤城杯 2021 流量分析

看分组也知道考http流量 是布尔盲注 过滤器筛选http流量 将流量包过滤分离 http tshark -r timu.pcapng -Y "http" -T json > 1.json这个时候取 http.request.uri 进一步分离 http.request.uri字段是我们需要的数据 tshark -r timu.pcapng -Y "http&quo…

fmql之CAN调试

刚刚把zynq的CAN调成功。那么现在就要把程序移植到fmql了。 老规矩,Procise导入vivado的.bd和.xci文件。 Procise下create block也可以,但是不能自动约束引脚,只能手动写代码。 PeripheralTest CanExample中用到了CAN0和CAN1:…

重生之 SpringBoot3 入门保姆级学习(11、日志的进阶使用)

重生之 SpringBoot3 入门保姆级学习(11、日志的进阶使用) 3.2.4 文件输出3.2.5 日志文档的归档与切割 3.2.4 文件输出 配置 application.properties # 日志文件名 如果不写路径默认就是在项目根路径建立 demo.log 文件 推荐写法 D:\\demo.log 路径 文…

虚拟机Ubuntu 22.04上搭建GitLab操作步骤

GitLab是仓库管理系统,使用Git作为代码管理工具。GitLab提供了多个版本,包括社区版(Community Edition)和企业版(Enterprise Edition)。实际应用场景中要求CPU最小4核、内存最小8GB,非虚拟环境。 以下是在虚拟机中安装社区版步骤:…

R语言ggplot2包绘制高端堆积柱状图

数据和代码获取:请查看主页个人信息!!! 关键词“高端堆积柱状图” 大家好,今天我将介绍如何使用ggplot2包绘制高端堆积柱状图。 本次绘图灵感来源于下面这篇文章,之所以复现这张图,有这么几个原…