
简介这套电商平台数据分析系统是面向计算机、自动化等相关专业学生开发的Python课程大作业/毕业设计资源覆盖从数据读取、预处理到可视化分析与报告输出的完整流程适用于电商订单数据、用户行为、RFM模型、销售趋势、复购率等典型分析场景。压缩包共30个文件以7个Python脚本为核心包括用户行为分析、渠道来源、RFM用户分层、销售趋势、复购率等模块搭配19张分析结果PNG图、3个pyc缓存文件及1份Markdown项目说明包体仅1.68MB结构清晰便于查阅复用。代码经过运行验证可直接运行或在此基础上二次开发作为期末课程设计、课程大作业甚至毕业设计参考均有较高借鉴价值。目前已有883人学习下载适合需要快速上手电商数据分析实战的学生与开发者。1. 电商平台数据分析系统这门课程大作业最值钱的地方不在代码量“Python课程大作业电商平台数据分析系统”这个标题在期末项目清单里往往不是最吸引眼球的那个但它可能是最容易让老师点头、也最能让简历上多一句人话的选择。它把 Python 基础语法、pandas 数据处理、数据可视化和一点 Web 展示串在同一条链路上先读一张销售订单表清洗出能用的字段算出销售额趋势、热销商品、客户分层这些业务指标再画成图、做成网页或者导成 Excel。这篇文章不替你把 zip 里的源码逐行讲一遍——那是不可能的——而是把这个标题背后最常见的实现方案拆透让你拿到任何一版源码都知道该看什么、该改哪里也有能力从零搭一套能演示的分析系统。适合 Python 课程设计、期末大作业以及想把第一份数据项目写到简历上的同学。2. 先定边界再写代码电商数据分析系统的五块核心功能与项目结构2.1 最小数据集长什么样订单表是最核心的输入电商数据分析系统的输入绝大多数情况下就是一张销售订单明细表。常见做法是 CSV 或 Excel包含订单号、下单时间、用户ID、商品ID、商品名称、单价、数量、订单金额、支付方式、收货省份这些字段。别小看这张表——数据分析系统里 80% 的工作量都发生在“确认这张表能不能算”上。字段名类型是否必需作用订单号字符串必需唯一标识一次交易用于计算订单量下单时间日期时间必需做时间维度聚合例如按日/按月销售额用户ID字符串/数值必需客户分层、复购率计算商品ID字符串较必需热销商品排名商品名称字符串建议展示层更友好数量整数必需计算销量单价浮点数建议计算原始金额订单金额浮点数必需销售额、客单价、RFM 的 M 值支付方式字符串可选支付渠道偏好分析收货省份字符串可选地域分布、物流分析真实项目中这张表往往不会太干净有缺失订单号、下单时间是字符串、金额列混着元字、同一用户有多个小号。所以拿到 zip 里的源码第一步永远是打开数据文件用 pandas 的df.info()和df.head(10)看类型和缺失再决定跳过哪一步。不要一上来就跑全流程那和考试不看题直接写答案一样。2.2 分文件组织代码为什么不能全写在一个 main.py 里很多大作业翻车不是功能没做出来而是所有逻辑全塞进一个 main.py数据清洗三百行、指标计算三百行、画图两百行最后别说导师连自己都找不到改哪里。一套能作为“系统”交付的源码我一般按模块分文件。典型的目录结构是ecommerce_analysis/ ├── data/ # 原始数据文件 │ └── orders.csv ├── output/ # 生成的图表和 Excel 报告 ├── src/ │ ├── __init__.py │ ├── data_loader.py # 读取数据 数据清洗 │ ├── indicators.py # 指标计算趋势/RFM/热销 │ ├── visualize.py # 图表生成 │ └── exporter.py # 导出 Excel ├── app.py # Flask 入口可选 ├── requirements.txt # 依赖清单 └── README.md # 使用说明模块拆分的好处有三个。第一答辩时可以说“数据清洗和指标计算解耦”这是老师爱听的架构词。第二改清洗逻辑不用重新跑指标节省调试时间。第三新增指标时只需要在indicators.py加函数不必动入口文件。Python 本身是解释型语言不强制分文件但项目一旦超过两百行不分文件的代价就是每个需求变更都要从头捋一遍代码。2.3 最小起步命令把依赖装好再跑第一张图不管拿到的是哪版源码先建一个干净的虚拟环境然后按 requirements.txt 安装依赖。最常见的整合版是 pandas matplotlib pyecharts flask openpyxl。如果你的环境是 Python 3.8 以上直接跑python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install pandas matplotlib pyecharts flask openpyxl参数说明python -m venv创建虚拟环境避免把包装进系统 PythonWindows 和 macOS/Linux 的激活命令不同路径区分反斜杠和斜杠。安装完成后可以跑一句快速验证——能输出版本号就算环境没问题import pandas as pd import pyecharts print(pd.__version__, pyecharts.__version__)这一步最常见的翻车点是 pyecharts 装不上或者装上后和 Python 版本不兼容。解决办法是换用pip install pyecharts1.4.0这类指定版本安装因为 2.x 的 API 和 1.x 差异较大网上大量教程还停留在 1.x 写法的阶段。3. 五大指标的计算逻辑与参数设置销售额、RFM 客户分层、热销商品3.1 销售额趋势分析按月聚合的粒度选择与时间字段处理销售额趋势是电商数据分析系统里第一个该做的指标也是所有图表的灵魂。常见错误是直接df.groupby(下单时间)[订单金额].sum()然后发现每个时间点都不同——因为原始下单时间精确到秒每行一个时间戳聚合结果极其稀碎。正确做法是先决定聚合粒度看一年的数据用“月”看一个季度的数据用“周”或“日”看一个月的促销活动用“日”。核心代码逻辑是这样import pandas as pd df pd.read_csv(data/orders.csv, encodingutf-8-sig, parse_dates[下单时间]) # 把下单时间转换成月粒度方便聚合 df[月份] df[下单时间].dt.to_period(M) monthly_sales df.groupby(月份)[订单金额].sum().reset_index() # 转换成字符串便于 pyecharts 在 X 轴展示 monthly_sales[月份] monthly_sales[月份].astype(str) print(monthly_sales.head())这段代码有两个关键参数。第一个是read_csv里的parse_dates[下单时间]作用是把字符串日期直接转成 pandas 的 datetime 类型后面才能用.dt.to_period()提取月份——如果不加这一步df[下单时间]是字符串.dt访问器会直接报错。第二个是to_period(M)M代表月粒度替代常用的resample(M)好处是它不要求把时间列设成索引写法更直观。最后.astype(str)把 Period 类型转成字符串否则 pyecharts 画图时会报“无法序列化 Period”的错误。实际数据分析里月粒度只能看出大趋势看不出促销活动前后的波动。如果数据覆盖了“双11”或“618”我会额外增加一个“按天聚合”的对照表只取大促前后两周的数据观察峰值在哪里出现。3.2 RFM 客户分层阈值参数决定你看待客户的维度RFM 是电商平台数据分析系统里价值最高的分析模块因为它能直接回答“谁是高价值客户、谁该挽回、谁在流失”。所谓 RFM是三个英文单词的缩写RRecency指客户最近一次下单距今多少天FFrequency指客户下单次数MMonetary指客户累计消费金额。R 越小越健康F 和 M 越大越有价值。RFM 的核心难点在阈值参数的设定。常见做法有两种分位法适合数据量大和业务定值法适合数据量小或业务规则明确。分位法代码长这样import pandas as pd # 假设 df 已经清洗过一行为一笔订单 reference_date df[下单时间].max() pd.Timedelta(days1) rfm df.groupby(用户ID).agg( Recency(下单时间, lambda x: (reference_date - x.max()).days), Frequency(订单号, count), Monetary(订单金额, sum) ) # 分段打分0~20% 为 1 分20%~40% 为 2 分……80%~100% 为 5 分 def score_by_quantile(series, reverseFalse): q series.quantile([0.2, 0.4, 0.6, 0.8]) def assign_score(x): if x q.iloc[0]: return 5 if reverse else 1 elif x q.iloc[1]: return 4 if reverse else 2 elif x q.iloc[2]: return 3 elif x q.iloc[3]: return 2 if reverse else 4 else: return 1 if reverse else 5 return series.apply(assign_score) rfm[R_score] score_by_quantile(rfm[Recency], reverseTrue) rfm[F_score] score_by_quantile(rfm[Frequency]) rfm[M_score] score_by_quantile(rfm[Monetary])这里的核心参数是[0.2, 0.4, 0.6, 0.8]四个分位点把数据切成五等份。理解这个代码有个关键R 和 F/M 的打分方向是相反的。R 代表距离上一次下单的天数天数越少越好所以recency传入reverseTrue间隔最小的那 20% 客户得 5 分。而 F频次和 M金额都是越大越好不用反转。打分完成后就可以组合R_score、F_score和M_score把客户分成八类例如“555”是核心高价值客户、“115”是刚流失的大客户等等。3.3 热销商品与地区分布聚合排序的两种常用姿势热销商品排行的实现比 RFM 简单得多但它能直观地反映“这个系统到底有没有在分析业务”。最常见做法是groupby聚合后排序然后取 Top N。N 这个参数直接决定了图表的信息密度——Top 5 适合做海报式大屏Top 10 适合答辩展示Top 20 就是内部运营视角再多了图表会糊成一团。# 热销商品榜按销量排行取前 10 product_sales df.groupby(商品名称).agg( 销量(数量, sum), 销售额(订单金额, sum) ).reset_index() top_products product_sales.nlargest(10, 销量) # 参数 10 可以按需调整代码里的nlargest(10, 销量)是 pandas 的快捷排序方法等价于sort_values(销量, ascendingFalse).head(10)但写法更短、意图更清晰。注意这里按“销量”排行而不是“销售额”是因为销售额容易脱离实际——单价高的商品可能只卖了一两件就上榜而按销量排才能找到真正的爆款。如果想要更全面可以增加一列“销售额”同时作为对照展示。地区分布的分析同理只是聚合键从商品名称换成收货省份图表类型从柱状图换成地图或横向条形图。横向条形图最实用因为中国省份名称是两个字为主放在 X 轴会挤在一起换成 Y 轴排列更易读。3.4 导出 Excel 报告让老师打开文件就能看到全部结论很多课程大作业的交付物只是代码和几张图这是不够的。更好的做法是增加一个导出模块把前面算好的指标一次性写入 Excel 的多个工作表。这一步工程量很小但对答辩分数的提升非常明显——老师不需要跑你的代码就能看到结果。import pandas as pd export_path output/电商数据分析报告.xlsx with pd.ExcelWriter(export_path, engineopenpyxl) as writer: monthly_sales.to_excel(writer, sheet_name销售额趋势, indexFalse) top_products.to_excel(writer, sheet_name热销商品, indexFalse) rfm.to_excel(writer, sheet_name客户分层) df.to_excel(writer, sheet_name订单明细, indexFalse)ExcelWriter 是 pandas 的导出引擎engineopenpyxl指定用 openpyxl 库写入.xlsx格式不加indexFalse会把索引也写成 Excel数据里多出一列无意义的编号。每个指标对应一个 sheet 的好处是结构清晰工作报告里可以直接引用文件路径。导出后打开检查一遍重点看时间列是不是变成了“2023-01-01 00:00:00”这种满屏串——是的话就在导出前对时间列.dt.strftime(%Y-%m-%d)格式化一遍。这一步很多人会漏掉直到老师打开文件说“日期都坏了”。4. 可视化选型与网页仪表盘让大作业更像一个系统4.1 pyecharts 还是 matplotlib演示效果与稳定性的取舍电商数据分析系统的可视化选型大多在 pyecharts 和 matplotlib 之间纠结。我的经验是如果只输出静态图用 matplotlib如果需要交互式网页演示用 pyecharts。matplotlib 的优点是稳定离线可用渲染任何中文字体都不需要额外配置输出 PNG 图片直接嵌入报告缺点是图表样式老气没有悬停提示答辩现场看起来就是“普通课程作业”。pyecharts 的优点是图表样式现代、自带交互鼠标悬停显示数值、缩放、图例切换网页端展示效果非常抓眼球答辩加分明显缺点是首次加载需要联网拉取 JavaScript 依赖如果你在无网络的教室演示图可能是空的。如果决定用 pyecharts一个常见参数是init_opts里的画布大小和主题from pyecharts.charts import Bar from pyecharts import options as opts bar ( Bar(init_optsopts.InitOpts(width800px, height400px, themelight)) .add_xaxis(monthly_sales[月份].tolist()) .add_yaxis(销售额, monthly_sales[订单金额].tolist()) .set_global_opts(title_optsopts.TitleOpts(title月度销售额趋势)) ) bar.render(output/monthly_sales.html)width和height控制图表输出尺寸单位是像素theme可以换成dark或infographic。render()是 pyecharts 的最终输出方法参数是生成的 HTML 文件路径。注意 pyecharts 1.x 的opts.InitOpts与 2.x 的参数略有差异如果是老版本源码换个参数名调整即可。4.2 用 Flask 把图表挂上网页一个最小的仪表盘骨架单独生成几个 HTML 文件的问题在于答辩演示时需要一个个打开浏览器标签页既不连贯也不像“系统”。更体面的做法是用 Flask 写一个极简服务把图表嵌进一个统一的仪表盘页面。Flask 是 Python 生态里最轻量的 Web 框架适合课程设计的演示场景。from flask import Flask, render_template import pandas as pd app Flask(__name__) app.route(/) def dashboard(): # 函数内读取已经算好的数据 df pd.read_csv(output/monthly_sales.csv) months df[月份].tolist() values df[订单金额].tolist() return render_template(dashboard.html, monthsmonths, valuesvalues) if __name__ __main__: app.run(debugTrue, port5001)这个代码有两个关键点。第一个是render_template(dashboard.html, monthsmonths, valuesvalues)Flask 默认去templates目录找dashboard.html并把后端算好的列表变量传进去。第二个是app.run(debugTrue, port5001)debugTrue保证代码改动后服务自动重启省去手动重启的步骤port5001指定端口因为 5000 端口在 macOS 上容易被 AirPlay 占用这是血泪经验。配套的templates/dashboard.html不需要复杂核心是用 ECharts 的 CDN 接住后端传来的数据。实际交付时我更倾向把图表数据通过 Flask 的 API 接口动态返回但课程设计阶段直接在模板渲染时把数据传入就够了。4.3 演示现场的几个交互细节网页仪表盘做出来后有四个现场细节一定要提前确认。第一pyecharts 生成的 HTML 里引用了外部 JavaScript CDN如果答辩教室没有网络图表区域会全空白——解决方案是把 pyecharts 依赖的 JS 文件下载到本地 static 目录再把模板里的 CDN 地址换成相对路径static/js/echarts.min.js。第二Flask 启动时终端会显示本机地址正常情况下用http://127.0.0.1:5001访问不要给老师演示localhost之外的地址尤其是不要用0.0.0.0那是给别人访问用的反而可能打不开。第三演示前先把浏览器打开并加载好页面不要在讲课现场开着模板改代码然后刷新一旦报错或者样式乱了现场重启服务的体感非常糟糕。第四确认模板文件路径——Flask 只认templates目录下的文件如果把 HTML 放在项目根目录render_template一定报TemplateNotFound这是最常见的新手翻车点。5. 避坑实录这些坑我替你先踩过了5.1 中文乱码从 CSV 读取到图表标题全乱——一切字符问题的总根源现象用pd.read_csv(orders.csv)读中文数据票打出来后显示“锟斤拷”或“é”样的乱码图表标题直接变成方块。原因CSV 文件的实际编码和 pandas 默认读取的编码不一致。Windows 下 Excel 导出的 CSV 默认是GBK或ANSI而 pandas 在 Linux/macOS 上默认按UTF-8读取遇到 GBK 编码必然乱码。解决读文件时显式指定编码最稳的写法是pd.read_csv(orders.csv, encodingutf-8-sig)。这个utf-8-sig比utf-8更好因为它会自动去掉 UTF-8 的 BOM 头Excel 另存的 CSV 用这个参数基本零报错。如果仍是乱码再试encodinggbk。方向不对后面所有分析都是建立在错误数据上的。5.2 日期列被识别成字符串聚合时报“Period dtype”错误现象对下单时间做.dt.to_period(M)时直接抛AttributeError: Can only use .dt accessor with datetimelike values或者聚合结果是一堆乱序字符串。原因读取 CSV 时没指定parse_datespandas 默认把下单时间当作字符串后面所有时间计算都失效。解决在read_csv里加parse_dates[下单时间]或者读取后用df[下单时间] pd.to_datetime(df[下单时间], format%Y-%m-%d %H:%M:%S)做一次显式转换。format参数建议写上否则 pandas 会自己猜格式在小样本数据上可能猜错。5.3 RFM 分位法在数据量小的时候翻车客户全挤在同一个分值现象只有两三百条订单、几十个客户的数据跑 RFM 分位打分结果大部分客户都是 3 分或 4 分客户分层根本没有区分度。原因分位法依赖样本量。只有 20 个客户时quantile([0.2, 0.4, 0.6, 0.8])的分位点可能重叠甚至相等导致阈值变形。解决小样本优先用业务定值法也就是直接指定 R、F、M 的阈值。例如指定“最近 30 天内下单为 5 分30~60 天为 4 分”F 和 M 同理。这份定值直接写入配置文件不要硬编码在函数里方便后面改。5.4 pyecharts 生成 HTML 打开后一片空白控制台报 404现象用浏览器打开生成的monthly_sales.html图表区域空白按 F12 看控制台有一堆红色 404 报错指向cdn.jsdelivr.net之类的地址。原因pyecharts 默认从 CDN 拉取 ECharts 的 JavaScript 依赖当前网络环境访问不到这个 CDN图表就渲染不出来。解决在 pyecharts 创建图表对象时添加JsHost参数把资源指向本地。具体做法是把 pyecharts 自带的地图/JS 文件复制进项目static目录然后指定bar.render(output/monthly_sales.html)后手动修改生成的 HTML 里的 CDN 路径。另一种更省事的方式是在模板里显式引入 ECharts 的本地文件让 Flask 提供静态资源服务。5.5 Flask 端口被占用导致服务启动失败现象运行app.run(port5001)时终端直接报Address already in use。原因上一个调试进程还没关闭或者系统内其他程序占用了端口。解决换一个端口再试或者先kill掉占用进程。lsof -i:5001可以找到占用进程的 PID确认无误后kill -9 PID再启动。实际调试中我一般定期检查debugTrue模式下产生的僵尸进程它们不会自动释放端口是调试阶段最常见的阻塞点。6. 交付前必做的验证用一份模拟数据给自己打分6.1 生成模拟订单数据的自检方案一套数据分析系统如果只在真实数据上跑通一次很难说它足够可靠。我会在交付前生成一份模拟数据验证清洗 → 指标 → 可视化 → 导出整条链路是否通。模拟数据的好处是你能预先知道结果大概长什么样——比如明明造了 1000 笔订单、200 个用户分析结果却只有 50 个用户出现那说明清洗环节有数据丢失问题立刻暴露。import pandas as pd import random import datetime # 造 1000 条模拟订单覆盖全年的销售场景 users [fU{random.randint(1000, 9999)} for _ in range(200)] dates pd.date_range(2023-01-01, 2023-12-31, freqD) rows [] for i in range(1000): rows.append({ 订单号: fD{i:06d}, 用户ID: random.choice(users), 下单时间: random.choice(dates) datetime.timedelta(hoursrandom.randint(0, 23)), 商品名称: random.choice([手机壳, 耳机, 充电宝, 数据线]), 数量: random.randint(1, 3), 订单金额: round(random.uniform(20, 800), 2) }) mock_df pd.DataFrame(rows) mock_df.to_csv(data/mock_orders.csv, indexFalse, encodingutf-8-sig)代码的关键参数是随机种子。如果希望结果可复现在文件开头加一行random.seed(42)否则每次跑得到的数据都不一样不利于自查。生成后把data_loader.py的路径参数改成data/mock_orders.csv跑一遍检查monthly_sales是否出现 12 个月的数据、Top 商品是否合理、RFM 客户分层是否四类都有分布。如果某一步报错按第五章的清单逐项排查。6.2 从课程作业升级到可复用轮子的两个方向如果你想让这套系统不仅交差还能在未来拿出来当作品集有两个方向值得花时间。第一个方向是参数配置化把 RFM 的阈值、Top N 的 N 值、图表尺寸全部提取到一个config.py或 yaml 文件里让系统不用改代码就能适配不同数据集。第二个方向是增加“自动探索式分析”在指标计算后追加一段代码自动识别异常值——比如某天销售额和前后 30 天中位数偏离超过 3 倍就自动标注“疑似计入促销补贴——需要人工确认”。这个能力让系统从“展示报表”变成“辅助决策”也正是数据分析岗位面试时最想听到的故事。我自己的习惯是每次拿到一套新数据永远先跑一次模拟数据自检再跑真实数据真实数据的结论和业务直觉明显冲突时先怀疑代码再怀疑数据。复盘近十年写分析工具的流程这套“模拟先行”的规矩帮我把大量的坑挡在了交付前而不是在答辩现场翻车。希望帮到你。本文还有配套的精品资源点击获取