ARTICLE DETAIL

资讯详情

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

Python电商数据分析系统:从订单CSV清洗到RFM分层与可视化

Python电商数据分析系统:从订单CSV清洗到RFM分层与可视化 简介电商平台数据分析是Python课程设计中的高频选题。这套源码提供了完整可运行的实现方案面向需要完成期末大作业或课程设计的高校学生也适合Python数据分析入门者对照学习。系统围绕销售趋势、回购率、RFM用户分群、渠道来源等核心维度展开分析各功能模块按独立Python文件组织清晰展示数据清洗、统计分析到可视化的完整链路用户可根据作业要求直接选取或组合模块。19张可视化图表以PNG形式随源码提供配合说明文档便于理解分析逻辑整个源码包共30个文件、约1.68MB以zip压缩包形式分发轻量易用。源码已本地验证可运行评审得分98分内容经助教老师审定兼具完成度与可读性目前已有197人学习下载是课程设计参考的优质选择。1. 电商大作业别再交“打印Excel”这套 Python 分析系统能让你直接落地答辩电商数据分析系统是 Python 大作业和课程设计里出现频率最高的选题原因很简单数据好找、逻辑直观、可视化效果好老师一看就知道你做了事。但绝大多数人交上去的版本是 Jupyter Notebook 里堆了几十个单元格图是 matplotlib 默认风格也没做用户分群和 RFM 模型——这种作业能过但拿不到高分。这套电商平台数据分析系统实现源码加文档说明解决的就是“作业完整度”问题它把数据预处理、订单分析、用户画像、商品销售排行、复购分析和可视化报告串成了一条完整链路照着跑能出图改参数能换数据集答辩时每张图背后都有对应代码和结论。适合的人群很明确期末要交 Python 大作业的本科生、做课程设计的专科生、准备毕业设计但不想从零搭框架的人。你不用理解每个算法的数学推导只要会跑 Python、能改文件路径就能在一小时内复现整套分析流程。下面我会用拆过的类似项目的经验把数据表结构、核心脚本逻辑、报表生成方式和最容易翻车的几个点都过一遍。2. 先搞懂这套系统的数据链路从 CSV 原始表到可视化看板这套系统的核心不是某个高深算法而是“数据怎么流动”。我拆解过的课程设计项目里凡是代码能直接跑通、报告能自圆其说的数据链路一定是清晰的。这套电商分析系统的链路分成四段原始数据读取 → 数据清洗与特征工程 → 多维度统计分析 → 结果可视化与结论输出。2.1 订单表结构这五个字段是整个系统的地基拿到源码后你先打开数据目录下的订单文件常见命名是orders.csv或者sales_data.csv。不管文件名是什么表里至少会包含下面这五个字段这也是所有后续分析的依赖字段名类型作用order_id字符串订单唯一标识去重用user_id字符串用户标识做复购和用户分层product_id字符串商品标识做销量排行order_amount浮点数订单金额做销售额趋势order_date日期下单时间做时间序列分析有些版本的源码会多出category商品类目、quantity购买数量、region地区字段这属于加分项后面做交叉分析会更好用。你在改数据的时候先别急着动代码用 Pandas 读一遍确认这几列存在且类型正确。import pandas as pd df pd.read_csv(data/orders.csv, encodingutf-8) print(df.dtypes) print(df.head())这段代码的作用是加载数据并检查字段类型。常见问题是order_date被读成了字符串而不是datetime64类型这会导致后面做月份聚合时排序错乱。如果发现类型不对用pd.to_datetime()手动转换。我的习惯是读进来之后先写一行df[order_date] pd.to_datetime(df[order_date])做强制转换避免后续所有时间相关的操作踩坑。2.2 预处理脚本缺失值、重复订单和异常金额的清洗逻辑数据清洗在课程设计里最容易草草了事但恰恰是老师重点看的部分。这套源码里有一个data_clean.py或者preprocess.py模块负责三件事删除完全重复的订单记录、处理order_amount中的缺失值或负值、把日期格式统一。def clean_orders(df): # 去除完全重复的记录基于所有列判断 df df.drop_duplicates() # 删除订单金额为空的行 df df.dropna(subset[order_amount]) # 过滤异常金额金额小于等于0视为无效订单 df df[df[order_amount] 0] # 重置索引避免清洗后索引断裂 df df.reset_index(dropTrue) return df这里有几个值得注意的设计点。drop_duplicates()默认基于所有列判断如果同一个订单号由于系统 bug 产生了多条记录且金额相同会被剔除但如果金额有细微差别就删不掉更严格的写法是subset[order_id]按订单号去重实际操作中建议改成后者。dropna(subset[order_amount])只针对金额列做空值检测不影响其他字段缺失的行这样避免把整行有用的信息都丢掉。过滤负值属于业务逻辑层防御电商场景里退款会产生负金额记录如果要做销售净额分析这部分数据可以保留但单独标记具体取舍取决于作业要求。2.3 分析库选型为什么用 Pandas 而不是 SQL 或纯 Python很多大作业选手纠结要不要用 SQL 做查询这套系统给了明确答案不需要。课程设计场景下数据量级撑死几万行Pandas 的 DataFrame 操作完全够用而且输出直接对接可视化库省去数据库连接这一步。纯 Python 写统计逻辑更不可取循环遍历几万行数据太慢而且代码量翻倍。Pandas 的groupby()、merge()、pivot_table()三个函数能覆盖电商分析百分之八十的需求。# 按月统计销售额趋势 monthly_sales df.groupby(df[order_date].dt.to_period(M))[order_amount].sum() # 用户复购统计 user_order_count df.groupby(user_id)[order_id].count() # 商品销量排行 product_sales df.groupby(product_id)[order_amount].sum().sort_values(ascendingFalse)这三行代码分别对应三个核心分析维度时间趋势、用户行为、商品表现。dt.to_period(M)是把日期截断到月份比手动提取year和month再拼接要简洁得多。sort_values(ascendingFalse)拿到的是降序排列的结果直接取前十条就是销售排行榜。如果你拿到手的源码里没有写这三段逻辑那说明分析部分不完整建议你按照这个思路自己补上这也是答辩时能讲清楚的关键。3. 核心分析模块拆解RFM 用户分层和商品销售排行实战数据分析系统能不能拿高分取决于有没有“洞察”不只是画几张图。这套源码里的两个亮点模块是 RFM 用户价值分层和商品销售排行它们用的是电商行业里通行的方法论能直接产出一段有说服力的结论。3.1 RFM 模型在 Pandas 里的标准实现四分位打分的完整代码RFM 是 Recency最近一次消费间隔、Frequency消费频率、Monetary消费金额三个维度的缩写。思路不复杂每个用户算三个指标然后按分位数分成高组和低组最终组合出 8 类用户。最不值钱的是一般挽留用户最值钱的是重要价值用户。import pandas as pd import datetime # 计算每个用户的 RFM 指标 snapshot_date df[order_date].max() datetime.timedelta(days1) rfm df.groupby(user_id).agg({ order_date: lambda x: (snapshot_date - x.max()).days, # R order_id: count, # F order_amount: sum # M }).rename(columns{ order_date: recency, order_id: frequency, order_amount: monetary }) # 四分位打分数值越大表现越好 rfm[r_score] pd.qcut(rfm[recency], 4, labels[4, 3, 2, 1]) rfm[f_score] pd.qcut(rfm[frequency].rank(methodfirst), 4, labels[1, 2, 3, 4]) rfm[m_score] pd.qcut(rfm[monetary].rank(methodfirst), 4, labels[1, 2, 3, 4])qcut是这个方案里的核心函数。它在做等频分箱每个分箱里的用户数量大致一致。注意一个坑frequency和monetary如果有大量相同的值qcut会报错所以先用rank(methodfirst)给数据加一个稳定排名垫底确保每个值都唯一。recency的得分方向是反的间隔天数越少得分越高所以 labels 是 4、3、2、1 倒着排的。snapshot_date取数据最大日期加一天这样不会出现 0 天间隔避免边界判断模糊。3.2 用户分层结果解读怎样从 8 类用户里找到最重要的 20%打分完成后需要计算综合分并归类通常加权方式是三个维度同权重相加。高价值用户是三个维度都高于均值的组合比如重要价值用户R 高 F 高 M 高重要发展用户R 高 F 低 M 高。在答辩里你只需要强调一个数字前 20% 的用户贡献了多少销售额。# 计算综合分 rfm[total_score] rfm[r_score].astype(int) rfm[f_score].astype(int) rfm[m_score].astype(int) # 定义用户标签 def rfm_label(row): if row[total_score] 9: return 重要价值用户 elif row[total_score] 6: return 重要发展用户 elif row[total_score] 4: return 一般保持用户 else: return 一般挽留用户 rfm[user_label] rfm.apply(rfm_label, axis1) # 统计各类用户占比和贡献 label_stats rfm.groupby(user_label).agg( user_count(user_id, count), total_amount(monetary, sum) ) label_stats[amount_ratio] label_stats[total_amount] / label_stats[total_amount].sum() * 100这段的核心决策在于total_score的阈值划分。阈值没有行业统一标准完全依赖四分位计算的分值分布你可以在答辩时说明这是相对分层而非绝对分层。apply配合自定义函数能处理多条件判断比np.where嵌套可读性高很多。最后算出的amount_ratio就是那个“20% 用户贡献 70% 销售额”的核心证据建议你在文档里把这句话写进分析结论。3.3 商品维度分析Top N 排行和类目占比的组合拳只有销售金额排行还不够还需要加一个类目占比分析让结论更立体。源码里的analyze_products.py或者类似脚本会完成这两步输出结果直接用于绘图。# Top 10 畅销商品 top10 df.groupby(product_id)[order_amount].sum().nlargest(10).reset_index() top10.columns [product_id, sales_amount] # 类目销售占比如果数据包含category字段 if category in df.columns: category_summary df.groupby(category)[order_amount].sum().sort_values(ascendingFalse) category_ratio category_summary / category_summary.sum() * 100nlargest(10)比sort_values().head(10)更直接性能也更好。类目占比如果原始数据没有category字段这段代码会自动跳过算是一个兼容性设计。我建议你在文档里给category_ratio画一个饼图它能直接回答“这个平台靠什么类目赚钱”的问题老师看到这句话就知道你的分析是有业务逻辑的。4. 可视化与报告输出用 Pyecharts 生成交互式 HTML 还是用 Matplotlib 静态图分析做完了最后一步是出图。这时候课设选手最常见的纠结是选 Pyecharts 还是 Matplotlib。建议你在动手前先把定位想清楚如果答辩现场是投屏展示Pyecharts 的交互式图表能让你手动悬停看数值观感好如果最终提交物是 Word 文档和 PDF 报告Matplotlib 的静态图更稳不依赖 HTML 环境。4.1 一组图表对应一组业务结论六个必出的分析图这套源码里至少包含六种图表对应六段分析结论。我在拆类似项目的时候习惯做一张对照表答辩时照着讲非常顺图表分析结论核心代码函数月度销售额折线图销售额波动趋势与峰值节点plt.plot()类目占比饼图核心收入来源结构plt.pie()用户 RFM 分层柱状图各价值层级用户数量分布plt.bar()商品销量 Top10 条形图畅销商品集中度plt.barh()复购用户占比环形图用户粘性与忠诚度评估plt.pie()wedgeprops时间段下单量柱状图用户活跃时段分布plt.bar()我一般会在写绘图代码前把结论先写出来再反向选图。比如“哪个时段用户最爱下单”这件事条形图比饼图传递信息更准人眼对长度比对角度敏感。这套源码的默认设置里时间维度是按月分析的如果你拿到的是日度数据改成按小时分析会有意外发现电商平台凌晨下单占比高是常态写进结论里会显得你做过额外探索。4.2 Matplotlib 中文字体显示乱码一个必须提前处理的坑用 Matplotlib 在 Windows 上画图最恼人的问题就是中文显示成方块。源码文档里通常会提示你加字体设置但很多人没注意就跳过了。上来直接画的后果就是图里全是小方块答辩时无比尴尬。解决办法是显式指定中文字体同时把负号的显示设置也一起修掉。import matplotlib.pyplot as plt # 指定中文字体Windows 常见为 SimHeimacOS 为 Arial Unicode MS plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] Falseaxes.unicode_minus这个参数是用来修复坐标轴负号显示成方块的问题的很多人漏了这一步。如果你用的是 Jupyter还可以用%matplotlib inline让图直接嵌入页面。如果你把系统换成了 macOS字体名需要改成Arial Unicode MS否则同样乱码。这一步做完再跑绘图脚本中文就正常了属于“一劳永逸”的操作。4.3 将图表和结论拼接成报告文档结构决定答辩观感好的课程设计文档需要遵循一个逻辑顺序背景与目标 → 数据说明与预处理 → 分析方法 → 可视化结果 → 结论建议。这套源码配套的文档说明里已经给出了一个可复用的框架你需要做的是把生成的图片插入对应位置并给每一张图配一段两三行的解读。文档中的分析结论不要只写“月销售额为 100 万元”要写“月销售额呈现 3 月峰值、11 月低谷的规律推测受大促活动和季节性影响”。前者是数据陈述后者是商业洞察。答辩时老师不关心你的代码有多复杂他关心的是你能不能用数据解释业务现象。文档里如果有“建议”部分尽量提两三条可执行的动作比如“针对重要价值用户发放专属优惠券”这就比空泛的“提高用户活跃度”有说服力。5. 避坑实战记录数据缺失、编码报错与可视化翻车的典型修复过程课程设计跑代码不会一帆风顺。这类电商数据分析项目的高频问题集中在数据读取、类型转换、绘图显示三个环节。我把拆项目过程中遇到的最常见的问题和修复方法整理成几条每个都是现象、原因、解决三步对应可以直接对照手头的报错信息操作。5.1 文件读取直接报 FileNotFoundError现象运行pd.read_csv()时报错提示文件路径不存在但文件明明就在项目目录里。原因终端的工作目录和项目根目录不一致。很多人用 VSCode 打开单个 py 文件运行但终端当前目录还在用户主目录下相对路径自然找不到文件。解决使用绝对路径读取或者把工作目录切换到项目根目录代码如下import os os.chdir(os.path.dirname(os.path.abspath(__file__)))os.chdir把工作目录切到当前脚本所在目录之后所有相对路径都基于项目根目录生效。这是最省事的方法比每次手动拼绝对路径可靠得多。5.2 CSV 文件编码导致中文乱码现象数据读进来了但中文列名或者中文字段显示成乱码。原因CSV 文件保存时可能是 GBK 编码而 Pandas 默认用 UTF-8 读取。解决显式指定编码读取。UTF-8 读不了就改用 GBK同时可以加参数enginepython兜底。df pd.read_csv(data/orders.csv, encodinggbk, enginepython)如果你的数据文件是别人给的多半是 GBK。如果文件是 Mac 或者 Linux 上传的多半是 UTF-8。我习惯的做法是先写一个探测代码用chardet判断真实编码但课程设计没有那么多时间直接encodingutf-8试跑报错就换gbk两分钟能解决。5.3 qcut 报 BinsError: Bin edges must be unique现象运行 RFM 打分代码时报ValueError: Bin edges must be unique。原因frequency和monetary字段中大量用户的值相同等频分箱时边界无法划分比如一百个用户里六十个都只买了一单。解决先对列做rank(methodfirst)再传入qcut或者改用自定义阈值分箱。rfm[f_score] pd.qcut(rfm[frequency].rank(methodfirst), 4, labels[1, 2, 3, 4])rank(methodfirst)给相同值分配不同的排名序号保证每个值唯一分箱边界就不会重复。这个坑极其隐蔽报错信息也不是很直观但修复成本很低代码无非多写一层函数调用。5.4 Matplotlib 绘制的图在上交的文档里丢失现象本地 Jupyter 里图正常显示但把 Notebook 导出成 Word 或 PDF 后图片无法显示。原因Notebook 内嵌图是 base64 编码存在 ipynb 文件里导出时依赖解释器重新执行部分导出器直接丢弃图片。解决把每张图显式保存成 PNG 再插入文档保存时设置dpi让图片更清晰。plt.savefig(output/monthly_sales.png, dpi150, bbox_inchestight)bbox_inchestight会让保存的图片自动裁剪空白边缘答辩页面看起来更紧凑。我一般把图片统一保存到output目录文件名和图表英文名对应插入文档时直接引用不会出幺蛾子。5.5 Pyecharts 生成了 HTML 但浏览器打开是空白页现象Pyecharts 生成的.html文件双击打开页面空白控制台报错找不到echarts.min.js。原因Pyecharts 默认从 CDN 引用了 ECharts 的 JS 文件而当前电脑没有外网访问能力。解决使用本地资源模式在初始化图表时指定renderer和Environment配置或者直接把源码里的 JS 文件下载到本地项目目录并引入。from pyecharts.globals import CurrentConfig, OnlineHost CurrentConfig.ONLINE_HOST ./js/把echarts.min.js放在项目js目录下即可。这条相当重要答辩教室的网络环境基本不可控提前改成本地引用是最稳妥的。6. 把静态分析升级成动态看板基于 Pyecharts 的简单交互探索前面第五步做的 Matplotlib 静态图够交作业但如果你想在答辩时有一个能现场演示的操作环节建议花半小时把核心图表换成 Pyecharts 的交互版本。这里有一个很实用的技巧把 Pyecharts 渲染的 HTML 文件嵌入一个简易的本地展示页面双击就能打开不依赖 Jupyter。Pyecharts 的调用方式和 Matplotlib 不太一样它是链式调用先创建图表对象再通过add()方法添加数据最后用render()输出 HTML。下面的代码生成一个按月销售的交互式折线图鼠标悬停能看到每个月的具体金额from pyecharts.charts import Line from pyecharts import options as opts monthly_data df.groupby(df[order_date].dt.to_period(M))[order_amount].sum() months [str(m) for m in monthly_data.index] amounts [round(v, 2) for v in monthly_data.values] line ( Line() .add_xaxis(months) .add_yaxis( 月销售额, amounts, is_smoothTrue, label_optsopts.LabelOpts(is_showFalse) ) .set_global_opts( title_optsopts.TitleOpts(title月度销售额趋势), tooltip_optsopts.TooltipOpts(triggeraxis) ) ) line.render(output/monthly_sales_chart.html)is_smoothTrue是让曲线变得圆滑去掉锯齿感的参数这在展示趋势时观感更好。label_optsopts.LabelOpts(is_showFalse)是关闭数据标签防止点太多的时候数字挤成一团。tooltip_optsopts.TooltipOpts(triggeraxis)设置悬浮提示鼠标在图表上移动时同一横坐标的所有系列值都会显示这是交互体验的重要一环。如果你想把多个图放在同一个页面展示可以使用Grid组件并行布局或者用Tab组件做成多标签切换这样相当于做了一个迷你版的分析看板。这套源码里如果已经包含了dashboard.py这类脚本说明作者已经帮你想好了展示方式你只需要替换数据文件路径后运行即可。如果源码里没有按上面这段代码思路补一个效果会立刻超出预期。代码跑通之后建议你验证两个核心结论的输出路径一是确认output目录下生成了预期数量的图片和 HTML 文件二是打开控制台确认没有报错和警告。如果出现 DataFrame 的SettingWithCopyWarning这说明你在切片后做了修改操作虽然不影响结果但答辩时被问到会露怯。提前复制一份df.copy()再处理能彻底消除这类警告。我在最近一次帮学生调试这个项目的过程中就遇到过把客户数据 CSV 从 Excel 另存后日期格式变成了2024/1/5而代码默认写的是2024-01-05结果所有月份聚合全乱了。从那以后我每次拿到新数据都会先执行一次字段类型探查确认order_date的格式和值域范围再决定要不要加解析参数parse_dates。这个大检查流程节省的调试时间远超多写的十行代码。希望这些拆解和踩坑记录能帮你在两周内把这份资源吃透交出一份站得住脚的课设作业。本文还有配套的精品资源点击获取
返回列表