ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

航空公司客户价值分析Python源码:LRFMC模型与K-means聚类实战

航空公司客户价值分析Python源码:LRFMC模型与K-means聚类实战 简介这份资源是面向数据分析与机器学习入门者的航空公司客户价值分析实战源码包围绕Python环境下的客户分群与价值预测展开适合希望把数据挖掘流程落到真实业务场景的学习者。包内共10个文件以5个xls和3个csv数据表为主覆盖原始数据、清洗后数据与标准化结果另有1个py脚本承载核心分析逻辑1个txt说明导入模块压缩包约17.13MB。已有891人学习下载。读者可借助完整数据与代码走通数据清洗、特征工程、K-means客户分群、客户生命周期价值估算及模型评估等环节理解从原始航空数据到客户价值结论的完整链路并对照脚本排查缺失值处理、特征选择与聚类参数设置中的常见问题适合作为课程设计或自学练手素材。1. 航空公司客户价值分析 Python 源码一份能直接跑通 LRFMC 模型的实战包手里这份航空公司客户价值分析Python源码.rar解压后是一套围绕航空会员数据做客户分群的完整脚本核心是把经典的 LRFMC 模型落到 Python 里跑一遍。目录里能看到air_data.csv原始数据、zscoredata.xls和zscoreddata.xls两份标准化中间结果、data_cleaned.csv与data_cleaned1.csv清洗产物还有code.py、explore.xls、tmp以及一份导入模块说明.txt。它解决的不是教你怎么装 Python这种入门问题而是给已经会点 pandas 的人一份能对照复现的客户价值分析流水线从原始宽表读入、缺失与异常处理、标准化、K-means 聚类到给每个客户打上价值标签。适合做数据分析课程设计、航空公司 CRM 方向毕设或者想拿真实业务数据练一遍聚类全流程的从业者。下面我按自己拆包的顺序把每一步的参数和坑讲清楚。2. 拆包先看数据字典air_data.csv 的字段与 LRFMC 口径2.1 原始字段到底对应哪个指标air_data.csv是整份源码的输入源头它是一张典型的航空会员宽表一行一个会员列里塞了几十项行为统计。要跑通后面的聚类先得把业务字段翻译成 LRFMC 五个维度否则code.py里那些列名你会看得一头雾水。常见做法是按下表映射业务字段示例名LRFMC 维度含义FFP_DATE/LOAD_TIMELLength入会时长用观测窗口减入会日期FLIGHT_COUNTFFrequency观测窗口内飞行次数LAST_TO_ENDRRecency最近一次乘机到观测窗口的天数SEG_KM_SUMMMonetary观测窗口内总飞行里程avg_discountCCoefficient平均折扣率反映舱位价值L 这一维在原始表里通常不是现成列得用LOAD_TIME - FFP_DATE算出来单位取月。这一步是后面所有分析的地基算错了整条流水线都偏。2.2 用 pandas 读入并确认规模先别急着跑code.py自己读一遍数据确认行列数和缺失情况比直接信脚本更稳import pandas as pd # 原始数据用 gbk 读航空类 csv 常见中文编码 data pd.read_csv(air_data.csv, encodinggbk) print(data.shape) # 先看有多少会员、多少字段 print(data.isnull().sum()) # 逐列缺失计数定位脏列 print(data[SUM_YR_1].describe()) # 看关键数值列的分布和极值逻辑说明encodinggbk是因为这类国内业务导出文件多为 GBK用默认 utf-8 会直接抛UnicodeDecodeError。isnull().sum()帮你快速找出哪些列缺失严重决定是删行还是填充。describe()看的是分位数和最大最小值异常值往往就藏在 max 那一栏。参数说明如果你的文件实际是 utf-8把 encoding 换掉即可SUM_YR_1、SUM_YR_2是两年票价和是后面清洗异常值的重点列不同版本字段名可能略有差异以你air_data.csv表头为准。2.3 为什么先做探索再清洗explore.xls这份文件就是探索阶段的产物源码作者显然先跑了一轮描述统计才动手清洗。我一般也会先落一份探索结果因为航空数据里有两类典型脏数据票价为 0 但里程不为 0 的记录可能是里程兑换票以及票价和折扣率同时缺失的记录。不先看清楚分布清洗阈值就只能拍脑袋。这一步不产出最终结果但决定了后面data_cleaned.csv的质量值得单独花时间。3. 数据清洗与标准化从 air_data.csv 到 zscoreddata.xls3.1 丢弃与保留的判定规则清洗的核心是两条规则源码里对应data_cleaned.csv和data_cleaned1.csv两个中间文件说明作者做了两轮。第一轮通常按票价和里程同时为 0 或同时缺失来丢第二轮再处理折扣率缺失。写成代码是这样# 规则一票价与里程同时为 0 或缺失的记录视为无效会员 data data[~((data[SUM_YR_1].isnull()) (data[SUM_YR_2].isnull()))] # 规则二票价为 0 但里程不为 0或票价为 0 但折扣率不为 0 的保留 index1 data[SUM_YR_1].notnull() data[SUM_YR_2].notnull() index2 (data[SUM_YR_1] ! 0) | (data[SUM_YR_2] ! 0) index3 (data[avg_discount] ! 0) | (data[SEG_KM_SUM] ! 0) data data[index1 index2 index3] data.to_csv(data_cleaned.csv, indexFalse, encodinggbk)逻辑说明index1保证两年票价都不为空index2要求至少一年票价非零排除纯零消费index3用折扣率或里程兜底避免把有里程贡献的兑换票误删。三个条件取交集是航空客户分析里比较通行的清洗口径。参数说明indexFalse避免多写一列行号污染后续读取encodinggbk与读入保持一致。如果你数据里字段名不同把SUM_YR_1/2、avg_discount、SEG_KM_SUM换成实际列名即可。3.2 LRFMC 五维的构造清洗完就要把宽表压成五列。L 用日期差算其余四列直接取import numpy as np # L入会时长单位月 data[L] (pd.to_datetime(data[LOAD_TIME]) - pd.to_datetime(data[FFP_DATE])).dt.days / 30 # R/F/M/C 直接映射 data[R] data[LAST_TO_END] data[F] data[FLIGHT_COUNT] data[M] data[SEG_KM_SUM] data[C] data[avg_discount] lrfmc data[[L, R, F, M, C]] lrfmc.to_excel(lrfmc.xlsx, indexFalse)逻辑说明dt.days / 30把天数折成月是 LRFMC 里 L 的常规口径用 30 而非 30.44 是为了和多数教材对齐。R 取LAST_TO_END是因为它本身就是距最近一次乘机天数越小代表越近。五列拼成lrfmc后单独存一份方便后面反复调用。参数说明pd.to_datetime对格式敏感如果日期列是2012/1/1这种斜杠格式也能解析若报错加format%Y/%m/%d显式指定。to_excel需要 openpyxl没装先pip install openpyxl。3.3 标准化为什么用 Z-Score 而不是归一化zscoredata.xls和zscoreddata.xls两份文件名字只差一个字母内容都是标准化结果说明作者至少跑过两版。LRFMC 五个维度量纲差异极大M 是里程动辄几十万C 是折扣率0 到 1 之间。直接丢进 K-means距离会被 M 完全主导聚类等于白做。所以必须标准化。from sklearn.preprocessing import StandardScaler scaler StandardScaler() lrfmc_z scaler.fit_transform(lrfmc) lrfmc_z pd.DataFrame(lrfmc_z, columns[Z c for c in lrfmc.columns]) lrfmc_z.to_excel(zscoreddata.xls, indexFalse)逻辑说明StandardScaler做的是 Z-Score均值 0 方差 1保留原始分布形状。相比 Min-Max 归一化它对极端值没那么敏感而航空数据里高里程客户天然是长尾用 Z-Score 更稳。列名加Z前缀是为了和原始列区分避免后面混淆。参数说明fit_transform一步完成拟合和转换注意标准化参数只能从训练数据学如果后面要预测新客户得复用同一个 scaler不能重新 fit。4. K-means 聚类与客户价值分层code.py 怎么读怎么改4.1 聚类数 k 怎么定code.py里最关键的一个参数就是 k。LRFMC 模型的标准做法是聚成 5 类对应五种客户价值层级但这不是硬规定得看你的数据。我一般先用肘部法扫一遍from sklearn.cluster import KMeans import matplotlib.pyplot as plt inertia [] for k in range(2, 9): km KMeans(n_clustersk, random_state42, n_init10) km.fit(lrfmc_z) inertia.append(km.inertia_) plt.plot(range(2, 9), inertia, markero) plt.xlabel(k); plt.ylabel(inertia) plt.savefig(elbow.png, dpi120)逻辑说明inertia_是簇内平方和随 k 增大单调下降拐点处就是相对合适的 k。random_state42固定随机种子保证每次结果可复现这在写报告时很重要。n_init10让算法跑 10 次不同初始化取最优避免陷进局部最优。参数说明k 范围取 2 到 8 是经验区间航空客户分群一般不会超过 8 类再多业务上没法落地。如果拐点不明显就回到业务管理层能接受的层级数通常就是 5 类。4.2 跑 5 类并给客户打标签确定 k5 后正式聚类并把簇编号映射成业务标签k 5 km KMeans(n_clustersk, random_state42, n_init10) km.fit(lrfmc_z) labels km.labels_ # 把簇编号拼回原始数据 result lrfmc.copy() result[cluster] labels # 看每个簇在五个维度上的均值判断它属于哪类客户 profile result.groupby(cluster).mean() print(profile)逻辑说明groupby(cluster).mean()是解读聚类结果的核心手段。哪个簇 M 和 F 高、R 小就是重要保持客户哪个簇 L 短、C 低可能是低价值新客。标签不是算法给的是你根据这张均值表人工命名的。参数说明labels_的顺序和lrfmc行序一一对应直接拼列不会错位。profile建议导出成 Excel 存档写分析报告时直接引用。4.3 五类客户的典型画像跑完上面那段你会得到一张五行的均值表。按 LRFMC 的经典解读大致对应簇特征客户类型运营策略方向F、M 高R 小重要保持客户优先维护专属权益F、M 较高C 高重要发展客户提升频次促升舱R 大F、M 低重要挽留客户触达唤醒防流失L 短各项偏低新客户培养习惯引导复购各项均低一般与流失客户低成本维护或放弃这张表不是源码里写死的是你跑完profile后自己填的。不同数据集均值会有出入但解读逻辑一致先看 M 和 F 定价值高低再看 R 定活跃度最后看 C 定质量。5. 避坑与排查这份源码跑不起来时先查这几条5.1 读 csv 报 UnicodeDecodeError现象pd.read_csv(air_data.csv)直接抛编码错误。原因文件是 GBK 或 GB2312pandas 默认 utf-8。解决加encodinggbk若仍报错试encodinggb18030它兼容范围更广。别用encodingutf-8, errorsignore那会静默吞掉乱码字符后面列名对不上更难查。5.2 日期列 to_datetime 解析失败现象算 L 时pd.to_datetime报OutOfBoundsDatetime或格式错误。原因日期列里混了空值或非标准格式。解决先data[LOAD_TIME].head()看实际长相再决定是否加format参数有缺失就errorscoerce转成 NaT 后统一 drop。这一步不处理干净L 会整列变 NaN。5.3 聚类结果每次都不一样现象重跑code.py客户分群变了。原因K-means 初始化随机没固定种子。解决KMeans里加random_state42和n_init10。这两个参数是复现性的后悔药写课程设计或交付报告时必须加否则答辩时被问为什么和上次不一样会很被动。5.4 标准化后列名对不上现象zscoreddata.xls读回来列名是 0、1、2、3、4后面按名字取列全报 KeyError。原因StandardScaler返回的是 numpy 数组丢了列名。解决转 DataFrame 时显式传columns[ZL,ZR,ZF,ZM,ZC]。这是新手最容易翻车的一处数组和 DataFrame 混用要格外小心。5.5 中间文件覆盖导致结果错乱现象zscoredata.xls和zscoreddata.xls两份文件内容对不上不知道哪份是最终版。原因作者跑了两版没清理文件名只差一个字母。解决自己复现时统一命名比如zscore_v1.xls并在脚本里注释清楚哪份对应哪次运行。血泪经验是别在同一个目录里留两个几乎同名的中间文件过两天你自己都分不清。6. 把聚类结果落成可交付的客户分层报告跑通聚类只是半程真正交付时得把profile那张均值表翻译成业务能看懂的分层结论。我一般会加一段自动打标签的逻辑省得每次手工对照# 按 M 和 F 的均值高低自动命名阈值用整体中位数 m_med result[M].median() f_med result[F].median() def name_cluster(row): if row[M] m_med and row[F] f_med and row[R] result[R].median(): return 重要保持客户 elif row[M] m_med and row[F] f_med: return 重要发展客户 elif row[R] result[R].median() and row[M] m_med: return 重要挽留客户 elif row[L] result[L].median(): return 新客户 else: return 一般与流失客户 profile[类型] profile.apply(name_cluster, axis1) profile.to_excel(客户分层报告.xlsx)逻辑说明用中位数当阈值而不是均值是因为 LRFMC 各维分布偏斜均值容易被高价值客户拉高中位数更能代表大多数。apply(axis1)逐行判断规则顺序有讲究——先判高价值再判挽留最后兜底避免一个客户同时命中多条规则时被误分类。参数说明阈值可以按业务调整比如航空公司更看重 M就把 M 的判定线提到 75 分位。profile里存的是各簇均值所以判断的是簇而非单个客户命名结果直接对应五类群体。验证分层是否合理有个简单办法把每个簇的客户数和总里程贡献占比算出来正常应该呈现少数高价值客户贡献大部分里程的二八分布。如果五类客户数均匀、里程贡献也均匀多半是 k 选错了或者标准化没做对得回头查第 3 章。我现在的习惯是每次跑完聚类先看这张贡献占比表数字不合理就不往下写报告。从那以后我每次交付客户分层前都强制走一遍均值表 贡献占比双验证再没出现过把低价值客户误标成重要客户的情况。希望帮到你。本文还有配套的精品资源点击获取
返回列表