
简介这份资源是面向计算机、自动化等相关专业学生的Python课程大作业电商平台数据分析系统完整实现包适合用作期末课程设计、毕业设计或个人练手项目。项目围绕电商订单数据展开涵盖数据读取、脏数据处理、数据分析与可视化、分析报告生成等完整流程涉及订单金额、支付金额、渠道来源、平台类型、退单拒付等业务字段并包含销售趋势、复购率、用户行为、RFM模型、渠道来源等多个分析模块。压缩包共30个文件以19个png可视化图表、7个py源码脚本、3个pyc编译文件及1个md项目说明为主整体约1.68MB目录结构清晰便于按模块查阅与二次开发。目前已有883人学习下载代码经过运行验证可直接运行参考。读者可从中获取完整的数据清洗思路、多维度分析实现方式、可视化图表产出以及项目说明文档具有较高的学习借鉴价值。1. 电商数据分析大作业这套 Python 源码能省下你多少返工时间如果你正在为课程大作业或者毕业设计找一个能跑通、有数据、有图表的电商数据分析项目这套 Python 源码值得先拆开看看。它不是一个空壳框架而是围绕电商订单数据做了完整的分析链路从读取原始订单表到清洗脏数据再到销售趋势、复购率、用户行为、渠道来源、RFM 模型五个分析维度最后输出可视化图表和分析报告。代码文件按分析模块拆分每个脚本对应一个业务问题结构清晰适合直接拿来改造成自己的作业。这套资源适合三类人一是计算机、自动化相关专业需要交课程设计的学生二是想快速搭一个数据分析 demo 的初学者三是需要参考电商分析指标体系怎么落地到代码的从业者。它的价值不在于算法多复杂而在于把「业务问题 → 数据处理 → 指标计算 → 可视化」这条链路走通了而且代码经过运行验证省去了自己从零踩坑的时间。2. 拆开源码包六个脚本各自解决什么问题2.1 文件结构与模块分工拿到压缩包后先别急着运行。把目录展开核心文件其实就六个 Python 脚本加一份项目说明。我一般会先扫一遍文件名判断每个脚本的职责边界这样后面改代码或者排错时能快速定位。文件名对应分析模块核心产出PythonDataAnalyse.py主入口/数据加载读取原始数据输出清洗后的数据集SalesTrend.py销售趋势分析按时间维度统计订单量和销售额变化RepurchaseRate.py复购率分析计算用户重复购买比例UserBehavior.py用户行为分析下单频次、支付转化等行为指标UserBehavior2.py用户行为扩展补充维度的行为分析ChanelSource.py渠道来源分析各渠道订单分布与转化对比RFM.pyRFM 模型用户价值分层输出 RFM 得分__pycache__目录里是.cpython-37.pyc文件说明这套代码是在 Python 3.7 环境下运行过的。如果你本地是 3.8 以上问题不大但建议先用 3.7 或 3.8 跑一遍避免个别库的兼容性问题。picture目录下是二十多张分析结果截图包括 RFM 分层图、渠道对比图、趋势图等可以直接参考最终输出效果。2.2 数据字段与业务含义项目说明里给了一张字段对照表这是理解后续所有分析逻辑的基础。原始数据包含十个字段id编号、orderID订单编号、userID用户编号、goodsID商品编号、orderAmount订单金额、payment支付金额、chanelID渠道编号、platformType平台类型、orderTime下单时间、payTime支付时间、chargeback退单拒付。这里面有几个字段在清洗阶段会重点处理。orderAmount和payment理论上应该一致或者支付金额略小于订单金额用了优惠券的情况如果出现负数说明是退款或者数据录入错误。payTime和orderTime的间隔如果过长比如超过 24 小时在电商场景下通常视为异常订单因为正常支付行为不会拖这么久。chargeback字段标记了退单拒付这部分数据在计算销售额时需要剔除否则会虚高。2.3 运行环境与依赖准备代码没有附带requirements.txt这是这类课程作业资源的常见情况。根据脚本里用到的库我一般会先装这几个pandas 做数据处理numpy 做数值计算matplotlib 和 seaborn 做可视化。如果你用的是 Anaconda这些库基本都自带了直接跑就行。# 建议先创建独立环境避免和系统 Python 冲突 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装核心依赖 pip install pandas numpy matplotlib seaborn装完之后先跑PythonDataAnalyse.py因为其他脚本依赖它输出的清洗后数据。如果这个脚本报错后面的分析都跑不起来。常见报错是文件路径问题代码里可能写的是相对路径你需要根据自己解压后的实际位置调整。提示如果运行时报ModuleNotFoundError先确认当前激活的环境里是否装了对应库。用pip list看一眼比盲目重装快。3. 数据清洗从原始订单表到可用数据集3.1 加载数据与初步探查PythonDataAnalyse.py是整个项目的入口。它做的事情可以概括为读文件 → 看数据长什么样 → 按业务规则过滤 → 输出干净数据。先看加载部分怎么写。import pandas as pd # 读取原始数据文件注意编码格式中文数据常用 gbk 或 utf-8 df pd.read_csv(data.csv, encodinggbk) # 初步探查看行数、列名、数据类型、缺失情况 print(df.shape) print(df.dtypes) print(df.isnull().sum()) print(df.head(10))这段代码的逻辑很直接先把数据读进来然后快速了解它的整体状况。shape告诉你有多少行多少列dtypes看每个字段的类型对不对比如orderTime应该是字符串或者 datetime 类型如果变成 object 且格式混乱后面解析时间就会出问题。isnull().sum()统计每列缺失值数量缺失严重的列要考虑是否保留。参数方面encoding是关键。如果读进来报UnicodeDecodeError换成utf-8或者gb18030再试。read_csv还有其他常用参数比如sep指定分隔符默认逗号header指定表头行号usecols只读需要的列。数据量大的时候加上usecols能省内存。3.2 按业务规则提取 2020 年数据项目说明里明确提到「提取 2020 年数据」这是第一个过滤条件。为什么要限定年份因为电商数据往往跨年不同年份的促销节奏、用户结构差异很大混在一起分析趋势会失真。先看时间字段怎么处理。# 将下单时间转为 datetime 类型方便后续按时间筛选 df[orderTime] pd.to_datetime(df[orderTime], errorscoerce) # 筛选 2020 年的数据 df_2020 df[(df[orderTime] 2020-01-01) (df[orderTime] 2021-01-01)].copy() print(f2020年数据量{len(df_2020)})pd.to_datetime的errorscoerce参数很重要。如果原始时间格式不统一比如有的写2020-01-01有的写2020/1/1不加这个参数会直接报错。加了之后解析失败的会变成NaT相当于缺失值后面可以统一处理。筛选条件用和组合避免2020-12-31 23:59:59这种边界数据被漏掉。3.3 处理支付时间间隔过长的异常订单正常电商下单后支付行为通常在几分钟到几小时内完成。如果payTime和orderTime间隔超过一天大概率是异常数据比如测试订单、系统补录或者用户下单后隔了很久才支付。这类数据如果保留会拉低支付转化率、拉长平均支付时长影响分析结论。# 计算支付间隔小时 df_2020[payTime] pd.to_datetime(df_2020[payTime], errorscoerce) df_2020[pay_interval_hours] (df_2020[payTime] - df_2020[orderTime]).dt.total_seconds() / 3600 # 保留支付间隔在 24 小时以内的订单同时排除未支付订单 df_valid df_2020[(df_2020[pay_interval_hours] 0) (df_2020[pay_interval_hours] 24)].copy() print(f过滤异常支付间隔后数据量{len(df_valid)})这里有个细节pay_interval_hours 0是为了排除支付时间早于下单时间的逻辑错误数据。虽然少见但脏数据里什么都有可能。dt.total_seconds() / 3600把时间差转成小时比直接看 timedelta 更直观。阈值 24 小时不是绝对的如果你的业务场景是预售或者分期支付这个阈值要放宽但课程作业场景下 24 小时是合理默认值。3.4 处理金额为负的异常记录订单金额和支付金额出现负数通常对应退款、撤单或者数据录入错误。在计算销售额、客单价这些指标时负数会直接拉低结果必须处理。# 排除订单金额或支付金额为负的记录 df_clean df_valid[(df_valid[orderAmount] 0) (df_valid[payment] 0)].copy() # 同时排除退单拒付标记为 1 的记录 if chargeback in df_clean.columns: df_clean df_clean[df_clean[chargeback] ! 1] print(f最终清洗后数据量{len(df_clean)}) df_clean.to_csv(cleaned_data.csv, indexFalse, encodingutf-8-sig)chargeback字段的处理容易被忽略。如果数据里有这个标记说明该订单已经退单计算实际销售额时不应该计入。to_csv的encodingutf-8-sig是为了让 Excel 打开时不乱码indexFalse避免多出一列索引。输出文件给后续分析脚本用所以命名要清晰我一般叫cleaned_data.csv。注意清洗步骤的顺序会影响结果。先按时间筛选再算支付间隔比反过来更合理因为时间范围外的数据本来就不参与分析先剔除能减少计算量。4. 五个分析脚本指标怎么算、图怎么出4.1 销售趋势分析按时间维度看订单量和销售额SalesTrend.py解决的是「业务随时间怎么变化」这个问题。常见做法是按天、按周或按月聚合看订单量和销售额的走势。核心代码通常长这样import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(cleaned_data.csv, encodingutf-8-sig) df[orderTime] pd.to_datetime(df[orderTime]) # 按天聚合统计每日订单量和销售额 daily df.groupby(df[orderTime].dt.date).agg( order_count(orderID, nunique), sales_amount(payment, sum) ).reset_index() # 画双轴图柱状图看订单量折线图看销售额 fig, ax1 plt.subplots(figsize(12, 5)) ax1.bar(daily[orderTime], daily[order_count], color#4C72B0, alpha0.7, label订单量) ax1.set_ylabel(订单量) ax2 ax1.twinx() ax2.plot(daily[orderTime], daily[sales_amount], color#DD8452, linewidth2, label销售额) ax2.set_ylabel(销售额) plt.title(2020年每日订单量与销售额趋势) fig.legend(locupper right) plt.tight_layout() plt.savefig(sales_trend.png, dpi150) plt.show()groupby后面用dt.date而不是dt.day是因为dt.day只取日期中的「日」部分跨月时会混淆。agg里用nunique统计订单数而不是count因为同一订单可能有多条商品记录去重才是真实订单量。双轴图适合展示两个量纲不同的指标左轴订单量、右轴销售额一眼能看出「量价关系」。参数调整方面如果想看周趋势把dt.date换成dt.isocalendar().week想看月趋势用dt.to_period(M)。dpi150保证图片清晰度写报告够用。颜色代码可以换成自己习惯的配色不影响逻辑。4.2 复购率与用户行为谁在反复买、行为路径什么样RepurchaseRate.py和UserBehavior.py关注的是用户维度。复购率的定义有多种常见的是「一定时间内购买两次及以上的用户占比」。代码实现上先按用户分组统计购买次数再算比例。# 统计每个用户的购买次数 user_orders df.groupby(userID)[orderID].nunique().reset_index() user_orders.columns [userID, order_count] # 复购用户购买次数 2 repurchase_users user_orders[user_orders[order_count] 2] repurchase_rate len(repurchase_users) / len(user_orders) print(f复购率{repurchase_rate:.2%})nunique再次出现确保统计的是不同订单数而不是记录数。复购率的分母是总用户数分子是复购用户数。这个指标对电商来说很关键因为获取新用户的成本远高于维护老用户。如果复购率低于 20%说明用户粘性不够可能需要看是不是商品品类或者促销策略的问题。UserBehavior.py和UserBehavior2.py通常会看下单频次分布、支付转化率、用户活跃时段等。比如按小时统计下单量能看出用户集中在哪个时间段活跃对运营排班和推送时机有参考价值。这两个脚本的差异可能在于分析维度不同一个看整体行为分布一个看特定用户群的行为特征。4.3 渠道来源与 RFM 模型从渠道对比到用户分层ChanelSource.py分析不同渠道的订单表现。chanelID字段标识了用户从哪个渠道进来可能是搜索、推荐、广告位等。按渠道分组统计订单量和销售额能看出哪个渠道贡献最大。channel_stats df.groupby(chanelID).agg( order_count(orderID, nunique), total_sales(payment, sum), user_count(userID, nunique) ).reset_index() # 计算各渠道客单价 channel_stats[avg_order_value] channel_stats[total_sales] / channel_stats[order_count] print(channel_stats.sort_values(total_sales, ascendingFalse))RFM.py是这套代码里相对复杂的部分。RFM 三个字母分别代表 Recency最近一次购买时间、Frequency购买频率、Monetary消费金额。思路是给每个用户在这三个维度上打分然后分层。# 以分析日期为基准计算 R 值 snapshot_date df[orderTime].max() pd.Timedelta(days1) rfm df.groupby(userID).agg( recency(orderTime, lambda x: (snapshot_date - x.max()).days), frequency(orderID, nunique), monetary(payment, sum) ).reset_index() # 按分位数打分1-5 分 rfm[R_score] pd.qcut(rfm[recency], 5, labels[5, 4, 3, 2, 1]) rfm[F_score] pd.qcut(rfm[frequency].rank(methodfirst), 5, labels[1, 2, 3, 4, 5]) rfm[M_score] pd.qcut(rfm[monetary], 5, labels[1, 2, 3, 4, 5]) # 组合 RFM 得分 rfm[RFM_score] rfm[R_score].astype(str) rfm[F_score].astype(str) rfm[M_score].astype(str) print(rfm.head())qcut按分位数切分保证每个分数段人数大致均匀。R 值越小越好最近买过所以标签是[5,4,3,2,1]倒序。F 值用rank(methodfirst)是为了避免相同购买次数导致分箱边界报错。最终 RFM 得分可以进一步映射成「重要价值客户」「重要保持客户」等标签这部分在RFM.png截图里能看到效果。提示RFM 的分箱数量不一定要用 5数据量小的时候用 3 或 4 更稳定。分位数切分要求数据分布不能太集中否则会报Bin edges must be unique错误。5. 避坑与排查跑这套代码时最容易翻车的五个地方5.1 中文乱码读进来是问号写出去也乱现象read_csv之后打印df.head()中文列名或者中文内容显示为乱码或者直接报UnicodeDecodeError。原因原始文件的编码格式和代码里指定的encoding参数不一致。Windows 下 Excel 导出的 CSV 常见gbk或gb18030而代码默认用utf-8。解决先试gbk不行换gb18030再不行用chardet库检测。写文件时统一用utf-8-sig这样 Excel 打开不会乱码。5.2 时间解析失败to_datetime报错或产生大量NaT现象执行pd.to_datetime时抛出ValueError或者转换后大量时间为NaT导致后续筛选数据量骤减。原因原始时间字段格式不统一比如混用了2020-01-01、2020/1/1、20200101等多种写法。解决加errorscoerce让无法解析的变成NaT然后检查NaT占比。如果超过 10%需要先统一格式可以用pd.to_datetime(df[orderTime], format%Y-%m-%d, errorscoerce)指定格式逐个尝试。5.3 分组聚合后索引丢失groupby结果和想象不一样现象groupby之后直接赋值或者合并发现列对不上或者reset_index之后多出一列奇怪的索引。原因groupby默认把分组字段设为索引后续操作如果不reset_index列名和索引会混在一起。解决养成习惯groupby之后要么用as_indexFalse要么链式调用.reset_index()。聚合后的列名用agg里的命名元组指定避免自动生成的列名难以理解。5.4 可视化中文显示为方框现象matplotlib画图时标题和轴标签里的中文变成一个个小方框。原因matplotlib默认字体不支持中文。解决在画图前设置字体。Windows 下用SimHeiMac 下用Arial Unicode MSLinux 下用WenQuanYi Micro Hei。plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 解决负号显示问题5.5 脚本之间的数据依赖断裂现象单独跑SalesTrend.py报FileNotFoundError提示找不到cleaned_data.csv。原因分析脚本依赖清洗脚本的输出文件如果没先跑PythonDataAnalyse.py或者输出路径不一致就会断链。解决按顺序执行先跑主入口脚本生成清洗数据再跑各分析脚本。如果路径不对统一改成绝对路径或者基于脚本位置的相对路径。我一般会在每个分析脚本开头加一句os.chdir(os.path.dirname(os.path.abspath(__file__)))确保工作目录正确。6. 进阶改造把课程作业变成能写进简历的项目这套代码跑通只是第一步。如果你想让它在简历上更有说服力或者作为毕业设计的底子有几个方向可以继续挖。第一个方向是加数据源。现在数据是静态 CSV可以改成从数据库读比如 MySQL 或者 SQLite。用sqlalchemy或者pymysql连接把read_csv换成read_sql整个分析链路不变但项目看起来更接近真实生产环境。from sqlalchemy import create_engine engine create_engine(mysqlpymysql://user:passwordlocalhost:3306/ecommerce) df pd.read_sql(SELECT * FROM orders WHERE orderTime 2020-01-01, engine)第二个方向是加自动化调度。把清洗和分析脚本串成一个流程用schedule库或者系统的定时任务每天跑一次输出日报。这样项目就从「一次性分析」变成了「持续监控」。第三个方向是加交互式看板。matplotlib的图是静态的换成plotly或者pyecharts可以生成 HTML 交互图表鼠标悬停能看到具体数值汇报的时候更直观。如果再加一层streamlit或者dash就是一个简易的 Web 分析工具。第四个方向是补文档和测试。课程作业通常不要求测试但如果你要放到 GitHub 上加一个README.md说明项目结构、运行方式、依赖列表再写几个pytest用例验证清洗逻辑整个项目的完整度会高很多。我自己的习惯是每次跑完分析脚本都会把关键指标输出到一个report.txt里包括数据量、清洗前后对比、复购率、RFM 分层结果。这样即使图表没保存核心结论也有记录。从那以后我每次做数据分析项目都强制走一遍「清洗 → 验证 → 分析 → 存档」的流程避免中间结果丢失导致返工。希望这套源码和上面的拆解能帮你少走弯路顺利把作业或者项目落地。本文还有配套的精品资源点击获取