ARTICLE DETAIL

资讯详情

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

Python电商数据分析系统实战:从数据清洗到RFM可视化

Python电商数据分析系统实战:从数据清洗到RFM可视化 简介这份资源是面向计算机、自动化等相关专业学生的Python课程大作业电商平台数据分析系统包含完整实现源码与使用教程说明可直接用于期末课程设计、课程大作业或毕业设计也适合作为个人练手项目。项目围绕电商业务展开涵盖数据读取、脏数据处理、数据分析及可视化、分析报告等环节涉及订单金额、支付金额、渠道来源、平台类型、退单拒付等字段并实现销售趋势、复购率、用户行为、RFM模型、渠道来源等分析模块。压缩包共30个文件以19个png可视化图表、7个py源码脚本、3个pyc编译文件及1个md项目说明为主整体约1.68MB目录结构清晰便于按模块查阅与二次开发。目前已有883人学习下载代码经过运行验证读者可从中获取完整的数据分析流程、脏数据处理思路、可视化呈现方式与项目说明文档具有较高的学习借鉴价值。1. 从一份课程大作业说起电商数据分析系统到底在分析什么很多人拿到「Python课程大作业电商平台数据分析系统」这类标题第一反应是去搜免费 Python 源码大全想直接下载一个能跑的东西交差。但真正动手跑过一遍就知道这类系统能不能用取决于三件事数据从哪来、指标怎么算、结果怎么呈现。标题里的「电商平台数据分析系统」本质是一套围绕订单、用户、商品三类核心表展开的统计与可视化流水线用 Python 把原始交易记录清洗成可读的指标再用图表把结论摆出来。它适合两类人一是需要交课程大作业的学生二是想用一份完整小项目练手 Python 数据处理和可视化的入门者。这篇文章不讲空泛概念而是把这类系统从环境搭建、数据建模、指标计算到可视化输出的完整路径拆开让你照着能复现也知道哪里容易翻车。2. 环境准备与项目结构把 Python 数据分析系统跑起来的第一步2.1 用 conda 还是 venv数据分析项目的环境选型电商数据分析系统依赖的库不算少核心是 pandas、numpy、matplotlib、seaborn如果要做交互式图表还会用到 pyecharts 或 plotly。这些库之间有版本耦合比如 pandas 2.x 对 numpy 版本有要求matplotlib 中文字体配置又和系统环境相关。我一般推荐用 conda 建独立环境原因是 conda 能同时管理 Python 版本和非 Python 依赖比如某些绘图库的底层 C 库比纯 pip 省心。如果你已经装了 Anaconda 或 Miniconda直接执行下面的命令建环境# 创建名为 ecom_analysis 的环境指定 Python 3.10 conda create -n ecom_analysis python3.10 -y # 激活环境 conda activate ecom_analysis # 安装数据分析核心库指定较稳定的版本区间 pip install pandas2.0.3 numpy1.24.3 matplotlib3.7.2 seaborn0.12.2 openpyxl3.1.2这里选 Python 3.10 而不是最新的 3.12是因为部分课程大作业里用到的旧版绘图库对 3.12 支持还不完整3.10 是目前兼容性最稳的版本。pandas 锁在 2.0.3 是为了避免 2.1 之后某些 API 变更导致老代码报错。openpyxl 是用来读写 Excel 的电商数据经常以 xlsx 格式给出没有它 pandas 读 Excel 会直接抛错。如果你不想装 conda用 venv 也可以命令换成python -m venv ecom_env # Windows ecom_env\Scripts\activate # macOS / Linux source ecom_env/bin/activate pip install pandas numpy matplotlib seaborn openpyxlvenv 的缺点是它只管 Python 包不管 Python 本身版本所以你系统里得有 3.9 以上的 Python。用python --version确认一下低于 3.9 的话 pandas 2.x 装不上。2.2 项目目录怎么摆让源码和教程说明各归其位一份能交作业、也能自己维护的电商数据分析系统目录结构不需要复杂但要有基本的分层。我一般会这样组织ecom_analysis/ ├── data/ │ ├── raw/ # 原始数据只读不改 │ └── processed/ # 清洗后的中间数据 ├── src/ │ ├── clean.py # 数据清洗脚本 │ ├── metrics.py # 指标计算脚本 │ └── visualize.py # 可视化脚本 ├── output/ │ ├── charts/ # 图表输出 │ └── reports/ # 统计结果表格 ├── config.py # 路径和参数配置 ├── main.py # 主入口 └── requirements.txt # 依赖清单这个结构的好处是数据、代码、输出三者分离。很多同学把所有文件堆在一个目录里跑几次之后自己都分不清哪个 csv 是原始的、哪个是改过的。data/raw里的文件永远不动所有清洗结果写到data/processed这样出错可以随时回退重跑。config.py里放路径配置避免脚本里到处写死绝对路径# config.py from pathlib import Path BASE_DIR Path(__file__).resolve().parent DATA_RAW BASE_DIR / data / raw DATA_PROCESSED BASE_DIR / data / processed OUTPUT_CHARTS BASE_DIR / output / charts OUTPUT_REPORTS BASE_DIR / output / reports # 确保输出目录存在 for p in [DATA_PROCESSED, OUTPUT_CHARTS, OUTPUT_REPORTS]: p.mkdir(parentsTrue, exist_okTrue)用pathlib而不是字符串拼接是因为它在 Windows 和 macOS 上都能正确处理路径分隔符。mkdir(parentsTrue, exist_okTrue)保证目录不存在时自动创建已存在时不报错这样脚本可以反复运行。2.3 依赖清单与一键复现requirements.txt是让别人能复现你环境的关键文件。在激活的环境里执行pip freeze requirements.txt这会导出当前环境所有包的精确版本。别人拿到你的项目后只需要pip install -r requirements.txt就能装出一模一样的环境。注意pip freeze会导出所有包包括间接依赖文件可能比较长但这是最保险的做法。如果你只想列直接依赖可以手写 requirements.txt但版本号要写清楚比如pandas2.0,2.1。提示如果你的项目要提交给老师或上传到代码托管平台不要把data/raw里的大文件一起传上去通常几十 MB 的 csv 就够大了。可以在 README 里说明数据来源或者放一个小的示例数据集。3. 数据清洗与指标建模电商订单表怎么变成能分析的格式3.1 电商数据常见的四种脏缺失、重复、异常、格式错乱真实的电商订单数据几乎没有直接能用的。我处理过的数据里最常见的问题有四类。第一是缺失值比如用户 ID 为空、订单金额为空这种记录要么补全要么剔除。第二是重复记录同一笔订单因为导出问题出现两次直接算总额会翻倍。第三是异常值比如订单金额出现负数或者大到离谱的数字可能是测试数据混进来了。第四是格式错乱日期字段一会儿是2024-01-01一会儿是2024/1/1pandas 读进来全是字符串。清洗脚本我一般这样写# src/clean.py import pandas as pd import numpy as np from config import DATA_RAW, DATA_PROCESSED def load_raw(filenameorders.csv): 读取原始订单数据统一按字符串读入避免类型推断错误 df pd.read_csv(DATA_RAW / filename, dtypestr, encodingutf-8) print(f原始数据行数: {len(df)}) return df def clean_orders(df): 清洗订单数据去重、处理缺失、修正类型 # 1. 去除完全重复的行 df df.drop_duplicates() print(f去重后行数: {len(df)}) # 2. 关键字段缺失的直接剔除 key_cols [order_id, user_id, order_date, amount] df df.dropna(subsetkey_cols) print(f剔除关键字段缺失后: {len(df)}) # 3. 金额转数值无法转换的置为 NaN 后剔除 df[amount] pd.to_numeric(df[amount], errorscoerce) df df[df[amount] 0] # 4. 日期统一格式 df[order_date] pd.to_datetime(df[order_date], errorscoerce) df df.dropna(subset[order_date]) # 5. 去除金额异常值超过均值 5 倍标准差的视为异常 mean, std df[amount].mean(), df[amount].std() df df[df[amount] mean 5 * std] print(f清洗完成最终行数: {len(df)}) return df if __name__ __main__: raw load_raw() cleaned clean_orders(raw) cleaned.to_csv(DATA_PROCESSED / orders_clean.csv, indexFalse)这段代码的逻辑是先读入原始数据并强制按字符串处理避免 pandas 自动把订单号里的前导零吃掉。然后依次做去重、剔除关键字段缺失、金额转数值、日期标准化、异常值过滤。每一步都打印行数变化方便你判断哪一步删多了。errorscoerce的作用是转换失败时置为 NaN 而不是报错这样后续可以统一剔除。异常值用 5 倍标准差而不是 3 倍是因为电商订单金额本身波动大3 倍容易把正常的大额订单误删。3.2 从订单表到用户表RFM 模型的三个维度怎么算清洗完订单数据后核心分析通常围绕用户价值展开。RFM 是最经典的电商用户分层模型三个字母分别代表 Recency最近一次购买时间、Frequency购买频率、Monetary消费金额。这三个指标能把用户分成重要价值客户、重要保持客户、一般客户等几类。计算 RFM 的代码如下# src/metrics.py import pandas as pd from config import DATA_PROCESSED, OUTPUT_REPORTS def compute_rfm(df, snapshot_dateNone): 基于订单数据计算每个用户的 RFM 指标 df[order_date] pd.to_datetime(df[order_date]) # 快照日期默认为数据中最大日期后一天 if snapshot_date is None: snapshot_date df[order_date].max() pd.Timedelta(days1) rfm df.groupby(user_id).agg( recency(order_date, lambda x: (snapshot_date - x.max()).days), frequency(order_id, nunique), monetary(amount, sum) ).reset_index() # 按中位数打标签简单二分 rfm[r_score] (rfm[recency] rfm[recency].median()).astype(int) rfm[f_score] (rfm[frequency] rfm[frequency].median()).astype(int) rfm[m_score] (rfm[monetary] rfm[monetary].median()).astype(int) # 组合成用户类型 def label(row): if row[r_score] 1 and row[f_score] 1 and row[m_score] 1: return 重要价值客户 elif row[r_score] 0 and row[f_score] 1 and row[m_score] 1: return 重要保持客户 elif row[r_score] 1 and row[f_score] 0: return 新客户 else: return 一般客户 rfm[user_type] rfm.apply(label, axis1) rfm.to_csv(OUTPUT_REPORTS / rfm_result.csv, indexFalse) return rfm这里的关键参数是snapshot_date它决定了 Recency 的计算基准。如果不指定默认用数据中最大日期加一天这样最近购买的用户的 Recency 接近 0。groupby(user_id)后分别用nunique算订单数、sum算总金额。打分部分用中位数做二分是最简单的做法实际业务中可能用四分位数分五档但课程大作业用二分足够说明问题。3.3 商品维度分析销量排行与品类占比除了用户维度商品维度也是电商分析的重点。常见指标包括各商品销量排行、各品类销售额占比、客单价等。这部分用 pandas 的groupby加sort_values就能完成def product_analysis(df): 商品维度分析销量排行和品类占比 # 单品销量排行 product_rank df.groupby(product_id).agg( sales(amount, sum), orders(order_id, nunique) ).sort_values(sales, ascendingFalse).reset_index() # 品类销售额占比 category_share df.groupby(category).agg( sales(amount, sum) ).reset_index() category_share[share] category_share[sales] / category_share[sales].sum() product_rank.to_csv(OUTPUT_REPORTS / product_rank.csv, indexFalse) category_share.to_csv(OUTPUT_REPORTS / category_share.csv, indexFalse) return product_rank, category_sharesort_values(sales, ascendingFalse)让销量最高的排在最前面。品类占比用总销售额做分母得到每个品类的份额。这两个结果表可以直接拿来做图表也可以导出成 Excel 交作业。4. 可视化与报告输出让分析结果能看懂、能交差4.1 matplotlib 中文字体配置不配就是一堆方框用 matplotlib 画图时中文默认显示成方框这是新手最常翻车的地方。解决办法是显式指定中文字体。Windows 上一般用 SimHeimacOS 上用 Arial Unicode MS 或 PingFang SCLinux 上需要先确认系统装了中文字体。# src/visualize.py import matplotlib.pyplot as plt import matplotlib import platform def setup_chinese_font(): 根据操作系统配置中文字体 system platform.system() if system Windows: matplotlib.rcParams[font.sans-serif] [SimHei] elif system Darwin: matplotlib.rcParams[font.sans-serif] [Arial Unicode MS] else: matplotlib.rcParams[font.sans-serif] [WenQuanYi Micro Hei] # 解决负号显示为方块的问题 matplotlib.rcParams[axes.unicode_minus] Falsefont.sans-serif指定字体列表matplotlib 会按顺序找第一个可用的。axes.unicode_minus设为 False 是为了让负号正常显示否则负号也会变成方框。如果你在 Linux 上跑先执行fc-list :langzh看看有哪些中文字体可用把名字填进去。4.2 四张核心图表销量排行、品类占比、RFM 分布、月度趋势一个完整的电商数据分析系统输出四张图基本能覆盖主要结论。第一张是商品销量 Top10 横向柱状图第二张是品类销售额占比饼图第三张是 RFM 用户类型分布柱状图第四张是月度销售额趋势折线图。def plot_top_products(product_rank, top_n10): 商品销量 Top N 横向柱状图 top product_rank.head(top_n).iloc[::-1] # 反转使最大值在顶部 fig, ax plt.subplots(figsize(10, 6)) ax.barh(top[product_id], top[sales], color#4C72B0) ax.set_xlabel(销售额) ax.set_title(f商品销售额 Top{top_n}) plt.tight_layout() plt.savefig(OUTPUT_CHARTS / top_products.png, dpi150) plt.close() def plot_category_pie(category_share): 品类销售额占比饼图 fig, ax plt.subplots(figsize(8, 8)) ax.pie(category_share[sales], labelscategory_share[category], autopct%1.1f%%, startangle90) ax.set_title(品类销售额占比) plt.savefig(OUTPUT_CHARTS / category_pie.png, dpi150) plt.close() def plot_monthly_trend(df): 月度销售额趋势 df[month] df[order_date].dt.to_period(M) monthly df.groupby(month)[amount].sum() fig, ax plt.subplots(figsize(12, 5)) monthly.plot(kindline, markero, axax, color#DD8452) ax.set_xlabel(月份) ax.set_ylabel(销售额) ax.set_title(月度销售额趋势) plt.tight_layout() plt.savefig(OUTPUT_CHARTS / monthly_trend.png, dpi150) plt.close()dpi150保证图片清晰度够用交作业打印也不糊。plt.close()必须加否则画多了会内存泄漏。to_period(M)把日期转成月份周期groupby 后就是每月汇总。markero让折线图的数据点可见方便看具体数值。4.3 用 pyecharts 做交互式图表作业加分项如果想让作业更出彩可以用 pyecharts 生成 HTML 交互图表鼠标悬停能看到具体数值。安装pip install pyecharts后from pyecharts.charts import Bar from pyecharts import options as opts def interactive_bar(product_rank, top_n10): 生成交互式柱状图 HTML top product_rank.head(top_n) bar ( Bar() .add_xaxis(top[product_id].tolist()) .add_yaxis(销售额, top[sales].round(2).tolist()) .set_global_opts( title_optsopts.TitleOpts(title商品销售额 Top10), xaxis_optsopts.AxisOpts(name商品), yaxis_optsopts.AxisOpts(name销售额), ) ) bar.render(str(OUTPUT_CHARTS / interactive_bar.html))pyecharts 输出的是 HTML 文件用浏览器打开就能交互。注意render的参数是字符串路径传 Path 对象要先转成 str。这个图表可以直接嵌到网页里也可以截图放报告。5. 避坑与排查跑电商数据分析系统时最容易翻车的五个地方5.1 中文乱码读 csv 报 UnicodeDecodeError现象pd.read_csv时报UnicodeDecodeError: utf-8 codec cant decode byte。原因Windows 上 Excel 导出的 csv 默认是 GBK 编码不是 UTF-8。解决读文件时指定encodinggbk或者先用记事本打开另存为 UTF-8。更稳妥的做法是写一个探测函数def read_csv_smart(path): for enc in [utf-8, gbk, gb18030]: try: return pd.read_csv(path, encodingenc) except UnicodeDecodeError: continue raise ValueError(f无法识别编码: {path})5.2 日期解析失败混合格式导致 NaT现象pd.to_datetime后大量日期变成 NaT后续按月分组全是空。原因数据里同时存在2024-01-01和2024/1/1两种格式pandas 默认按一种解析。解决加formatmixed参数pandas 2.0 支持或者先用str.replace(/, -)统一分隔符再解析。如果版本低用pd.to_datetime(df[date], infer_datetime_formatTrue)。5.3 金额字段带货币符号转数值全变 NaN现象pd.to_numeric后金额列全是 NaN。原因原始数据里金额是¥128.00或$99.9这种带符号的字符串。解决先清洗再转换df[amount] df[amount].str.replace(r[¥$,], , regexTrue) df[amount] pd.to_numeric(df[amount], errorscoerce)正则[¥$,]把货币符号和千分位逗号都去掉再转数值。5.4 分组后索引丢失groupby 结果对不上现象groupby之后想按原列名取值发现列变成了索引。原因groupby默认把分组键设为索引reset_index()忘了加。解决养成习惯groupby后接.reset_index()或者用as_indexFalse参数df.groupby(user_id, as_indexFalse)[amount].sum()5.5 图表保存空白savefig 在 show 之后现象保存的图片是空白的但屏幕上显示正常。原因先调了plt.show()画布被清空后再savefig就什么都没了。解决先savefig再show或者干脆不在脚本里show只保存文件。用面向对象写法fig, ax plt.subplots()比plt.plot()更不容易出这个问题。6. 把系统做成可复用的分析模板我的三个私藏技巧跑通一次电商数据分析系统不难难的是让它能反复用、换一份数据也能跑。我自己的习惯是把它做成模板而不是一次性脚本。第一个技巧是把所有可调参数抽到config.py里比如 Top N 的数量、异常值的标准差倍数、RFM 打分用中位数还是四分位数。这样换数据时只改配置不动业务代码。第二个技巧是给每个脚本加if __name__ __main__入口既能单独运行调试也能被main.py统一调度。第三个技巧是输出报告时同时生成一份 Markdown 摘要把关键数字写进去交作业时直接复制。# main.py 统一调度 from src.clean import load_raw, clean_orders from src.metrics import compute_rfm, product_analysis from src.visualize import setup_chinese_font, plot_top_products, plot_category_pie, plot_monthly_trend def run(): setup_chinese_font() raw load_raw() cleaned clean_orders(raw) rfm compute_rfm(cleaned) product_rank, category_share product_analysis(cleaned) plot_top_products(product_rank) plot_category_pie(category_share) plot_monthly_trend(cleaned) print(分析完成结果已输出到 output/ 目录) if __name__ __main__: run()验证系统是否正常我一般看三个点清洗后行数是否在合理范围删太多说明清洗规则太激进、RFM 各类用户占比是否合理如果全是「一般客户」说明打分阈值有问题、图表文件是否都生成且不为空。这三个检查做完基本能确认系统跑通了。最后说个血泪经验不要等到交作业前一天才跑数据。电商数据清洗经常遇到各种玄学问题编码、日期格式、金额符号每一个都可能卡你半天。提前跑一遍把坑踩完后面就顺了。希望帮到你。本文还有配套的精品资源点击获取
返回列表