ARTICLE DETAIL

资讯详情

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

Python校园消费行为分析毕设实战:从数据清洗到RFM聚类可视化

Python校园消费行为分析毕设实战:从数据清洗到RFM聚类可视化 简介这份资源面向计算机相关专业的毕业设计、课程设计及期末大作业需求者提供一套基于Python的学生校园消费行为分析完整项目。项目经导师指导并获评审99分认可代码完整可运行适合零基础小白上手实践也可作为数据分析方向的实战练习素材。压缩包共8个文件约10.08MB以py源码文件为主辅以docx说明文档、txt依赖清单、md说明及gitignore等配置项结构清晰便于按模块查阅。项目围绕某高校校园消费行为数据集展开涵盖数据预处理、消费特征建模与行为分析等核心环节配套文档对设计思路与实现过程做了系统说明读者可据此理解DFM模型在消费行为分析中的应用逻辑并快速复现完整流程。目前已有189人学习下载适合需要完整项目方案、可运行代码与配套文档的学习者参考使用。1. 从一份 99 分毕设拆起这套校园消费行为分析到底能跑出什么如果你正在为计算机毕业设计选题发愁或者手头有个课程设计要交又不想从零造轮子那这套「基于 Python 的学生校园消费行为分析」值得先看一眼。它不是那种只有几页 PPT 的空壳项目而是把数据、源码、说明文档三样东西都凑齐了一个某高校校园消费行为数据集.zip一个src目录下的model.py、analysis.py、init.py外加一份基于 DFM 模型的分析文档和requirements.txt。换句话说拿到手就能跑跑完就能出图出结论直接往论文或答辩 PPT 里搬。这套东西适合谁第一类是做毕业设计但不想在数据采集上耗时间的同学第二类是想练手 Pandas、Matplotlib、Sklearn 的 Python 入门者第三类是需要一个完整「数据清洗→建模→可视化」闭环案例的课程设计选手。它解决的核心问题就一个把零散的校园一卡通消费记录变成能讲出故事的分析报告。下面我按自己拆包复现的顺序把这份资源从环境配置到模型调参再到踩坑一层层剥开。2. 环境配置与数据加载把 requirements.txt 变成能跑的 Python 环境2.1 依赖清单里藏着哪些版本坑先看requirements.txt。这类毕设项目最常见的翻车点就是依赖版本对不上尤其是 Pandas 和 NumPy 的兼容性。我一般不会直接pip install -r requirements.txt而是先打开文件扫一眼。常见的写法是只写包名不写版本号比如pandas、numpy、matplotlib、scikit-learn、seaborn。这种写法在 2024 年之后的 Python 3.11/3.12 环境下大概率能装上但如果你用的是 Python 3.8 或更早Pandas 2.x 会直接报ImportError。我的习惯是先建虚拟环境再装依赖。虚拟环境的好处是万一装崩了删掉重来不影响系统 Python。命令如下# 创建虚拟环境python3 -m venv 是标准做法 python3 -m venv venv # 激活虚拟环境Windows 用 venv\Scripts\activate source venv/bin/activate # 升级 pip避免旧版 pip 解析依赖时抽风 pip install --upgrade pip # 安装依赖如果 requirements.txt 没锁版本建议手动加几个关键版本 pip install -r requirements.txt逻辑说明venv是 Python 自带的虚拟环境模块不依赖第三方工具。激活后所有pip install都只作用于当前目录不会污染全局。参数上如果你发现requirements.txt里写了pandas1.5.3但你的 Python 是 3.12那这个版本可能没有对应的 wheel 包需要改成pandas2.0或者降 Python 版本。这一步没有后悔药只能提前看。2.2 数据集加载与字段初探数据文件是某高校校园消费行为数据集.zip解压后通常是一个 CSV 或 Excel。我拿到手第一件事不是急着跑analysis.py而是先自己用 Pandas 读一遍看看字段名、数据类型、缺失值。常见字段包括学号、性别、年级、专业、消费时间、消费金额、消费地点、消费类型餐饮/超市/洗澡/网费。下面这段代码是我每次拆新数据集都会跑的「体检脚本」import pandas as pd # 读取 CSV注意编码校园数据常见 gbk 或 utf-8 df pd.read_csv(校园消费数据.csv, encodinggbk) # 看前 5 行确认列名和分隔符没读错 print(df.head()) # 看数据类型和非空数量快速定位缺失值 print(df.info()) # 看数值型字段的分布消费金额有没有负数或异常大值 print(df.describe()) # 看分类字段的取值比如消费地点有哪些 print(df[消费地点].value_counts())逻辑说明encodinggbk是血泪经验很多高校导出的 CSV 默认是 GBK用 UTF-8 读会报UnicodeDecodeError。df.info()能一眼看出哪些列有缺失比如「专业」列如果非空数量少于总行数后面建模就得考虑填充或剔除。df.describe()里的min和max是关键如果消费金额出现负数可能是退款记录需要单独处理。这一步做完你才对数据长什么样有底而不是盲目跑model.py。3. 源码结构拆解init.py、model.py、analysis.py 各管什么3.1 init.py 里的初始化逻辑与路径陷阱src/init.py通常是项目的入口初始化脚本负责设置随机种子、定义全局路径、加载配置。我见过很多毕设项目把路径写死成C:\Users\xxx\Desktop\...换台电脑直接崩。拆包时先打开这个文件看它有没有用os.path.dirname(__file__)做相对路径。如果没有你得手动改。常见写法如下import os import random import numpy as np # 设置随机种子保证每次跑出来的聚类结果一致 SEED 42 random.seed(SEED) np.random.seed(SEED) # 用当前文件位置推导项目根目录避免绝对路径 BASE_DIR os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DATA_DIR os.path.join(BASE_DIR, data) MODEL_DIR os.path.join(BASE_DIR, models) # 确保输出目录存在不然保存图片时会报错 os.makedirs(MODEL_DIR, exist_okTrue)逻辑说明os.path.abspath(__file__)拿到当前脚本的绝对路径dirname两次就回到项目根目录。这样无论你把项目拷到 D 盘还是 U 盘路径都能自动适配。os.makedirs(..., exist_okTrue)是防止目录已存在时报FileExistsError。参数上SEED42是惯例你可以改成任意整数但改了之后聚类结果会变论文里的图得重新跑。3.2 model.py 里的 DFM 模型与聚类实现model.py是核心建模文件。根据说明文档项目用的是 DFM 模型。DFM 在不同领域含义不同在消费行为分析里常见做法是先用 RFMRecency、Frequency、Monetary做特征工程再用 K-Means 或 DBSCAN 做用户分群。我拆过的类似项目里model.py一般包含三个函数build_rfm()、train_kmeans()、save_model()。下面是我根据这类项目还原的典型代码结构import pandas as pd from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler import joblib def build_rfm(df): # 假设 df 有 学号、消费时间、消费金额 三列 df[消费时间] pd.to_datetime(df[消费时间]) # 以数据集最后一天为基准计算最近一次消费距今天数 snapshot_date df[消费时间].max() pd.Timedelta(days1) rfm df.groupby(学号).agg({ 消费时间: lambda x: (snapshot_date - x.max()).days, # Recency 学号: count, # Frequency 消费金额: sum # Monetary }) rfm.columns [R, F, M] return rfm def train_kmeans(rfm, n_clusters4): # 标准化因为 R/F/M 量纲差异大 scaler StandardScaler() rfm_scaled scaler.fit_transform(rfm) # 训练 K-Meansn_clusters 需要根据肘部法则调整 kmeans KMeans(n_clustersn_clusters, random_state42, n_init10) kmeans.fit(rfm_scaled) rfm[cluster] kmeans.labels_ return rfm, kmeans, scaler # 保存模型方便下次直接加载 joblib.dump(kmeans, models/kmeans.pkl)逻辑说明build_rfm里用snapshot_date减去每个学号最后一次消费时间得到 R 值count得到 F 值sum得到 M 值。这是消费行为分析的标准套路。StandardScaler必须加否则 M 值可能几千会完全压制 R 值几十。n_init10是 Sklearn 新版参数旧版默认就是 10显式写出来避免警告。joblib.dump保存模型下次预测不用重新训练。参数上n_clusters4是常见分群数但你需要用肘部法则或轮廓系数验证不能拍脑袋。3.3 analysis.py 的可视化输出与图表解读analysis.py负责出图。这类项目通常输出四类图消费金额分布直方图、各年级消费对比柱状图、消费地点饼图、RFM 聚类散点图。我拆包时最关注的是它有没有用plt.rcParams设置中文字体因为 Matplotlib 默认不支持中文图里全是方框。典型修复代码如下import matplotlib.pyplot as plt import seaborn as sns # 设置中文字体Windows 用 SimHeiMac 用 Arial Unicode MS plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 解决负号显示问题 # 画消费金额分布 plt.figure(figsize(10, 6)) sns.histplot(df[消费金额], bins30, kdeTrue) plt.title(学生消费金额分布) plt.xlabel(消费金额元) plt.ylabel(频数) plt.savefig(output/消费金额分布.png, dpi300) plt.show()逻辑说明font.sans-serif指定中文字体axes.unicode_minusFalse让负号正常显示。dpi300是论文插图的标准分辨率低了打印会糊。sns.histplot的kdeTrue会叠加核密度曲线比单纯直方图好看。参数上bins30决定柱子数量数据量大可以调到 50数据量小调到 15。这一步跑完你就能拿到能直接贴进论文的图。4. 避坑与排查跑这套源码时最容易翻车的五个地方4.1 编码报错 UnicodeDecodeError现象运行pd.read_csv()时抛出UnicodeDecodeError: utf-8 codec cant decode byte...。原因校园一卡通系统导出的 CSV 多为 GBK 或 GB2312 编码而 Pandas 默认用 UTF-8。解决把encoding参数改成gbk如果还报错就试gb18030这是 GBK 的超集覆盖更全。4.2 中文字体显示为方框现象plt.show()出来的图里标题和轴标签全是小方块。原因Matplotlib 默认字体不含中文字形。解决在analysis.py开头加plt.rcParams[font.sans-serif] [SimHei]Mac 用户改成[Arial Unicode MS]。如果还不行检查系统是否真的装了该字体Linux 服务器上通常没有 SimHei需要手动上传字体文件并注册。4.3 K-Means 聚类结果每次跑都不一样现象同样的数据两次运行model.py聚类标签完全不同。原因K-Means 初始质心随机且没有固定随机种子。解决在KMeans()里加random_state42并在init.py里设置np.random.seed(42)。另外n_init参数在新版 Sklearn 中默认是auto显式设为10更稳定。4.4 路径写死导致换电脑就崩现象把项目从笔记本拷到台式机运行报FileNotFoundError。原因init.py或analysis.py里用了绝对路径比如C:\Users\张三\Desktop\data.csv。解决全部改成基于__file__的相对路径参考 3.1 节的写法。如果项目里有多处硬编码用编辑器的全局搜索替换把C:\Users\...替换成os.path.join(BASE_DIR, ...)。4.5 依赖版本冲突导致 Sklearn 导入失败现象from sklearn.cluster import KMeans报ImportError或AttributeError。原因requirements.txt里写的scikit-learn版本与当前 Python 不兼容或者 NumPy 版本过高导致 Sklearn 编译失败。解决先pip list看已装版本然后pip install scikit-learn1.3.0指定一个稳定版。如果还不行降 Python 到 3.10这是目前兼容性最好的版本。5. 从跑通到跑好RFM 分群调参和论文图表打磨的两个进阶技巧5.1 用肘部法则确定最佳聚类数model.py里默认n_clusters4但 4 群不一定适合你的数据。我一般会跑一遍肘部法则看 SSE簇内误差平方和随 K 值变化的拐点。代码如下import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler scaler StandardScaler() rfm_scaled scaler.fit_transform(rfm[[R, F, M]]) sse [] k_range range(2, 11) for k in k_range: kmeans KMeans(n_clustersk, random_state42, n_init10) kmeans.fit(rfm_scaled) sse.append(kmeans.inertia_) # inertia_ 就是 SSE plt.figure(figsize(8, 5)) plt.plot(k_range, sse, markero) plt.xlabel(聚类数 K) plt.ylabel(SSE) plt.title(肘部法则确定最佳 K 值) plt.savefig(output/肘部法则.png, dpi300) plt.show()逻辑说明kmeans.inertia_是每个样本到其簇中心的距离平方和K 越大 SSE 越小但拐点之后下降变缓。选拐点对应的 K 值比如 K4 或 K5。参数上k_range从 2 到 10 足够覆盖校园消费分群场景。这张图也可以直接放进论文的「模型选择」章节比空口说「我选了 4 类」有说服力得多。5.2 把聚类结果翻译成业务标签跑出cluster列之后别直接写「第 0 类、第 1 类」论文里要翻译成「高消费低频群」「低消费高频群」这种业务语言。做法是算每个簇的 R、F、M 均值然后对比# 算每个簇的 RFM 均值 cluster_summary rfm.groupby(cluster)[[R, F, M]].mean() print(cluster_summary) # 根据均值大小打标签示例逻辑 def label_cluster(row): if row[M] rfm[M].mean() and row[F] rfm[F].mean(): return 高价值活跃群 elif row[M] rfm[M].mean() and row[F] rfm[F].mean(): return 高消费低频群 elif row[M] rfm[M].mean() and row[F] rfm[F].mean(): return 低消费高频群 else: return 低价值沉默群 cluster_summary[标签] cluster_summary.apply(label_cluster, axis1) print(cluster_summary)逻辑说明groupby(cluster).mean()得到每个簇的 RFM 中心点然后跟全局均值比。高于均值就是「高」低于就是「低」。这样每个簇就有了可解释的业务含义论文里的「用户画像」章节直接能用。参数上阈值用的是全局均值你也可以用中位数取决于数据分布是否偏斜。从那以后我每次拆这类毕设项目都强制先跑一遍数据体检脚本再改路径和字体最后才动模型。这套流程帮我省了至少三次通宵重跑的时间。希望这份拆解能帮你把这份资源真正跑起来而不是让它躺在硬盘里吃灰。本文还有配套的精品资源点击获取
返回列表