ARTICLE DETAIL

资讯详情

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

Python电商销售数据分析实战:从订单清洗到可视化看板

Python电商销售数据分析实战:从订单清洗到可视化看板 最近正好做完一个电商销售数据的 Python 分析项目从拿到原始订单表到输出可视化结论整个流程踩了不少坑也沉淀出一套可以直接复用的方法。这篇博文就把完整过程拆开揉碎了讲适合刚接触 Python 数据分析、想找一个真实项目练手的朋友也适合已经在做电商数据、但总觉得分析效率不高的从业者。我会从设计思路、数据清洗、指标体系、可视化实现一直讲到问题排查尽量还原项目现场的真实状态。1. 项目整体设计与分析思路拆解1.1 先别急着写代码拿到数据后我要先想清楚什么很多初学者拿到一张几千行的订单表第一反应就是pd.read_excel()然后df.head()看完几行数据就开始groupby一顿操作。这种思路不能说错但很容易陷入“为了分析而分析”的怪圈——图是画了一堆最后老板问“所以我们要做什么”的时候答不上来。我把这个项目的第一步定为“需求澄清”。所谓电商销售数据分析核心目标无非是回答这几个问题整体卖得怎么样——对应 GMV、订单量、客单价、退款率等大盘指标。趋势怎么样——按天、周、月的销售额走势判断增长还是下滑。什么东西卖得好——品类、商品的销售排行找出头部贡献者。谁在买——用户分层、复购情况、地域分布。有什么异常——大促峰值、数据突变、以及可能存在的脏数据。这次实战的数据来自某电商平台导出的订单明细字段包括订单号、下单时间、支付时间、商品类目、商品名称、数量、单价、实付金额、用户ID、省份城市等一共约13万条时间跨度从2023年1月到2023年12月。拿到这种数据我会先列一份“问题清单”先看哪几个维度、用哪些指标回答、最终用什么形式输出。这一步决定了后面的代码结构。1.2 为什么用 Python 而不是 Excel工作量与可复用性的权衡在电商销售分析这件事上Excel 不是不能用13万条数据用透视表也可以跑但问题在于效率和多维分析的灵活性。比如想同时做“月度同比”和“新老客复购分析”在 Excel 里要反复调字段、拉透视表、写公式而用 Python 写一套脚本改一个日期参数就能复用下个月的数据。Python 在电商数据分析中的核心优势我认为有三点数据清洗能力缺失值、重复值、异常值处理可以用几行代码完成且逻辑可复现。分析维度扩展性从整体大盘到用户分群到商品结构代码组织好后切换分析视角非常快。可视化和报告一体化pandas 处理数据、matplotlib/seaborn 画图、最后导出汇总表格一条龙完成。所以这个项目定下来的技术栈是pandas 做核心的数据加工numpy 辅助计算matplotlib 和 seaborn 做静态图表pyecharts 做一份简单的交互式 HTML 看板。1.3 分析框架的四层结构我把整个分析流程拆成四个层级这也是我一直推荐给团队的思路L1 数据层读取数据、字段检查、类型转换、清洗去重。L2 指标层定义和计算核心指标比如 GMV、UV、订单量、转化率、客单价、复购率。L3 维度层按时间、品类、地区、用户四个维度进行钻取观察指标的变化和结构。L4 结论层把各维度分析结果汇总成商业结论和建议。下面整个项目就是围绕这条线展开的。2. 数据清洗与核心指标计算的实操要点2.1 字段检查是第一步也是最容易被敷衍的一步拿到数据后我的第一个动作是跑一段基础检查代码确认每列的数据类型、缺失比例、重复情况。信息密度很低的工作但千万别跳过很多坑就是数据里藏着雷导致的。import pandas as pd import numpy as np df pd.read_excel(2023_orders.xlsx) print(df.shape) print(df.dtypes) print(df.isnull().sum()) print(df.duplicated(订单号).sum())项目里这张表有 28 列其中比较关键的字段原始情况如下字段名原始类型样本值存在的问题订单创建时间字符串2023/1/3 14:23类型为 object需转 datetime实付金额字符串¥129.00含货币符号需清洗后转 float商品数量整数2正常可保留用户ID整数881234存在缺失约0.3%省份字符串广东省少量含空格和错别字订单状态字符串已完成需过滤“已退款”“待付款”第一遍跑下来发现几个典型问题一是实付金额字段带人民币符号和千分位逗号如果不处理后续聚合全是0二是订单创建时间是字符串没法直接做时间趋势分析三是存在约 213 条重复订单号可能是系统重试或导入错误四是用户ID有少量空值直接删除会影响后面的用户分析需仔细评估。2.2 金额和时间字段的清洗技巧字段规范才不被坑处理金额字段的常见做法是把符号和逗号都去掉再转成浮点数。我一般用str.replace配合正则一步到位df[实付金额] ( df[实付金额] .astype(str) .str.replace(¥, , regexFalse) .str.replace(,, , regexFalse) .astype(float) )时间字段则用pd.to_datetime转换同时需要决定按“订单创建时间”还是“支付时间”作为时间维度。电商分析中我更推荐用支付时间因为创建订单后可能取消支付时间才代表实际成交。代码里可以直接提取年月日和月df[下单时间] pd.to_datetime(df[订单创建时间]) df[日期] df[下单时间].dt.date df[月份] df[下单时间].dt.to_period(M)注意dt.date返回的是对象类型用于按天分组基本没问题要是想画坐标轴平滑曲线最好还是保留完整的datetime字段。实际工作中我用to_period(M)比较多方便按月份做汇总。2.3 重复值处理不能一把梭要看场景213 条重复订单号听起来直接删就行。但这里有个细节如果同一订单号的整行内容完全相同才是真重复但有时候是同一订单号对应多件不同商品这是正常的“订单-商品”明细结构。所以我不会盲目按订单号去重而是先按全部关键列去重再针对数据内部逻辑判断。df.drop_duplicates(inplaceTrue) key_cols [订单号, 商品名称, 商品数量, 实付金额] df_dedup df.drop_duplicates(subsetkey_cols, keepfirst)实战中这一轮清洗掉的是完全重复的记录数量大约 100 多条。剩下一些同订单号不同商品的明细它们对订单量统计有影响——聚合时需要注意按订单号去重统计订单数不能直接对明细行数数订单量。2.4 核心指标的计算口径为什么每个指标都要说清楚定义数据分析中最容易翻车的就是指标口径不一致。同一个“客单价”有人用 GMV ÷ 订单数有人用 GMV ÷ 支付用户数给到的结论差异非常大。我在项目开始前列了一张指标口径表强烈建议大家在分析前使用同样方法指标名称计算口径计算公式GMV 支付总金额已完成待发货待收货订单的实付金额总和sum(实付金额)订单量去重后的订单总数len(订单号.unique())客单价实付金额总和 ÷ 去重订单数GMV / 订单量件单价实付金额总和 ÷ 总商品件数GMV / sum(商品数量)复购率购买次数≥2的用户数 ÷ 总购买用户数见下文分组计算品类GMV占比某品类GMV ÷ 全品类GMVgroupby 后除以总量当时统计订单量直接用 df 的行数后来发现不对因为明细到商品一级一个订单号可能出现多行。正确写法是order_cnt df[订单号].nunique() gmv df[实付金额].sum() customer_cnt df[用户ID].nunique() unit_price gmv / order_cnt这类看似简单的计算在 Excel 里点两下能做但 Python 的优势在于口径写进代码里成为“可复用资产”下个月再来一份数据直接跑同一套函数就行。2.5 用户复购率分析用透视表实现分用户统计用户行为分析中复购率是核心指标。计算逻辑是先按用户ID分组统计每个用户的购买次数按订单号去重再判断次数是否≥2最后计算人数占比。user_buy_cnt ( df.groupby(用户ID)[订单号] .nunique() .reset_index() .rename(columns{订单号: 购买次数}) ) user_buy_cnt[是否复购] np.where(user_buy_cnt[购买次数] 2, 1, 0) repurchase_rate user_buy_cnt[是否复购].mean() print(f支付用户数: {user_buy_cnt.shape[0]}) print(f复购用户数: {user_buy_cnt[是否复购].sum()}) print(f复购率: {repurchase_rate:.2%})这个项目算出来的复购率约 23% 也就是接近四分之一的用户一年内买过两次以上。放在电商行业里属于中等偏上。如果把复购率按月份拆开看还能发现新客召回的最佳时间窗口——这个点后面单独讲。3. 实操过程从清洗到可视化看板的完整实现3.1 时间趋势分析发现销售波动的关键清洗完数据先做大盘。我习惯用groupby按日汇总 GMV 和订单量再用 matplotlib 画折线图。这一步的目的不是直接得出结论而是“肉眼找异常”比如双11是否正常、某天数据是否暴跌。daily_gmv df.groupby(日期)[实付金额].sum() daily_orders df.groupby(日期)[订单号].nunique() fig, ax1 plt.subplots(figsize(14, 5)) ax1.plot(daily_gmv.index, daily_gmv.values, color#2878B7, linewidth1, label日GMV) ax1.set_ylabel(GMV (元)) ax1.set_title(2023年每日销售趋势, fontsize14) ax2 ax1.twinx() ax2.bar(daily_orders.index, daily_orders.values, alpha0.3, color#9AC9DB, label日订单量) ax2.set_ylabel(订单量) plt.show()从趋势图观察全年销售有几个明显峰值集中在 3月、6月和11月。3月可能是春季上新6月是年中大促11月则对应“双十一”周期。需要注意的是峰值前后的剧烈波动部分源于促销活动真实需求曲线需要剔除活动期再做平滑。月度汇总能更好地看清结构性变化month_gmv df.groupby(月份)[实付金额].sum().reset_index() month_gmv[月份] month_gmv[月份].astype(str) print(month_gmv)用barplot画月度柱状图时会自动按每年月份排序但要注意月份是 Period 类型时直接画图会有些奇怪我一般先astype(str)再画保证 x 轴刻度可读。3.2 品类结构与TOP商品分析二八法则的验证品类结构分析是老板最关心的部分之一因为它能直接指导备货和运营重点。这里使用groupby汇总每个品类的 GMV、订单量和销量然后计算占比。cate_summary ( df.groupby(商品类目) .agg( 品类GMV(实付金额, sum), 品类订单量(订单号, nunique), 品类销量(商品数量, sum) ) .sort_values(品类GMV, ascendingFalse) .reset_index() ) cate_summary[GMV占比] cate_summary[品类GMV] / cate_summary[品类GMV].sum() cate_summary[累计占比] cate_summary[GMV占比].cumsum()运行后看一眼数据前3个品类的 GMV 占比超过 64%前5个品类占比超过 82%。这符合典型的二八法则少数品类贡献了大部分销售额。画帕累托图时用柱状图展示各个品类的绝对 GMV用折线展示累计占比在 80% 的位置画一条辅助参考线一目了然。对单品同样做 TOP10 排名结果发现头部商品集中在“零食礼盒”和“家居清洁”两类。这说明运营策略可以考虑爆款做引流中长尾做利润。这部分内容如果你只给老板一张图不加解释价值会大打折扣。3.3 地区分布分析发掘高潜市场省市维度的分析能回答“哪里卖得好”以及“是否还有增长空间”。先把空白省份和“未知”地区过滤掉然后按省份聚合 GMV直接取 TOP15 画横向柱状图。province_gmv ( df[df[省份].notna()] .groupby(省份)[实付金额] .sum() .sort_values(ascendingFalse) .head(15) ) plt.figure(figsize(9, 8)) province_gmv.plot(kindbarh, color#2878B7) plt.xlabel(GMV (元)) plt.gca().invert_yaxis() plt.title(销售金额 TOP15 省份, fontsize13) plt.show()在这份数据里广东省、浙江省、江苏省排在前面合计贡献超过 52%。比较有意思的发现是贵州省的客单价出奇地高核心原因是当地订单集中在高单价家电品类。这提示我们不能单看 GMV 排名还要结合平均客单价和品类结构做交叉分析。把“省份”和“品类”做成透视表能快速找到类似“贵州 家电”这样的隐藏高价值组合。3.4 用户分层与复购分析挖掘增长空间复购率计算完以后我进一步按“购买次数”做分层看看用户购买次数的分布结构。最常见的分层方式是 1次新客、2~3次回头客、4次及以上忠诚客。用cut函数离散化后统计人数占比bins [0, 1, 3, 999] labels [新客(1次), 回头客(2-3次), 忠诚客(4次)] user_buy_cnt[用户分层] pd.cut(user_buy_cnt[购买次数], binsbins, labelslabels) layer_dist user_buy_cnt[用户分层].value_counts(normalizeTrue) print(layer_dist)项目结果显示新客占比 77%左右回头客 14%忠诚客 9%。这里能给出的运营启示非常清晰新客基数大但流失快需要针对购买一次后 30 天内的用户做召回忠诚客虽然占比不高但贡献 GMV 可观——计算一下发现前 9% 忠诚客贡献了接近 35% 的 GMV。做用户分析时我特别建议做一个“高价值用户名单”具体的做法是筛选出购买次数≥4次且累计金额≥1000元的用户ID导出给运营做定向维护。3.5 可视化输出的几个实用细节图表美观度在公司汇报中往往被低估。我分享几个亲测有效的细节中文字体问题macOS 上用plt.rcParams[font.sans-serif] [Arial Unicode MS]Windows 上用SimHeiLinux 服务器上常需要安装中文字体否则坐标轴中文全变方框。柱状图数值标签用for循环在柱子上缘添加文本避免一堆数字要靠猜。折线图的平滑在plot中设置marker和linewidth比默认样式专业很多。配色统一我用一套固定的公司主色深蓝 #2878B7、浅蓝 #9AC9DB、橙 #FF8C00而不是每次都让 matplotlib 自动换色。3.6 用 pyecharts 快速生成交互式看板静态图适合写报告但业务同事会更喜欢交互式看板。项目最后我用 pyecharts 生成了一个单文件的 HTML 看板包含三张图月度趋势折线、品类占比饼图、省份地图如果安装地图包。Pyecharts 的 API 风格和 matplotlib 差异较大但生成 HTML 很方便。from pyecharts.charts import Line from pyecharts import options as opts line ( Line() .add_xaxis(month_gmv[月份].tolist()) .add_yaxis(月度GMV(元), month_gmv[GMV].round(0).tolist(), is_smoothTrue) .set_global_opts(title_optsopts.TitleOpts(title2023年月度销售趋势)) ) line.render(monthly_trend.html)只要数据是标准 DataFrame这种脚本30分钟能跑完。看板最大的价值是让不懂 Python 的同事也能自己 hover 看数值减少沟通成本。4. 常见问题排查与避坑技巧实录4.1 读入 Excel 时金额变成字符串、日期变乱码电商导出的 Excel 许多都混有货币格式pandas 默认会把它读成字符串。碰到这种情况不要急着改 dtype先df.head()看一眼实际样本。如果全是“¥12,399.00”这种格式用我前面提到的 replace 方案即可。如果有些单元格是文本“--”或“NULL”则pd.to_numeric(..., errorscoerce)会统一变成 NaN方便后续填充或删除。4.2 groupby 之后指标对不上没有先过滤异常订单一开始我在分析时把所有订单状态都算进去了结果发现 GMV 金额和平台后台对不上。排查后发现原因是“已退款”和“已关闭”订单也包含在导入表里。解决方法是先定义有效订单子集valid_status [已完成, 待收货, 待发货] df_valid df[df[订单状态].isin(valid_status)]只在过滤后的数据上做指标计算数值才与后台一致。这条经验非常重要建议每个分析项目的开头就确认订单状态字段的口径。4.3 内存占用过高或 pandas 卡死13 万条数据不至于卡死但如果拿到 500 万行以上的订单流水内存占用就会很严重。两个优化方向只用需要的列读入pd.read_excel(..., usecols[...])减少内存。把存储型字段转成category类型比如订单状态、商品类目、省份等低基数列能显著压缩内存。for col in [订单状态, 商品类目, 省份]: df[col] df[col].astype(category)先dtypes看一下哪几列的object对象多转成category后内存占用能减少一半以上。4.4 图表中文乱码Linux 环境最容易遇到。我通常在脚本最前面统一设置字体避免每次换环境都踩坑import matplotlib.pyplot as plt import platform if platform.system() Windows: plt.rcParams[font.sans-serif] [SimHei] elif platform.system() Darwin: plt.rcParams[font.sans-serif] [Arial Unicode MS] else: plt.rcParams[font.sans-serif] [WenQuanYi Micro Hei] plt.rcParams[axes.unicode_minus] False如果 Linux 上提示不存在字体还需要安装fonts-wqy-zenhei或手动放字体文件到 matplotlib 字体目录。4.5 透视表操作中出现的隐坑pd.pivot_table是处理多维分析的好帮手但常遇到两个问题一是聚合函数默认是mean如果忘记指定aggfuncsum算出来的金额完全不对二是有 NaN 的时候索引会变成浮点型导致后续合并出错。所以我在用透视表时都会写明dropnaFalse看情况填充或者最后用reset_index()清理索引。4.6 日期坐标轴太密集日粒度数据跨度一年的折线图x 轴标签如果每天显示不拥挤才怪。解决方法是设置MaxNLocator或直接指定若干均匀刻度from matplotlib.ticker import MaxNLocator ax1.xaxis.set_major_locator(MaxNLocator(nbins12))这样只用显示约 12 个刻度整体可读性会大幅提升。5. 项目复盘与扩展方向到这个环节项目的基本分析闭环已经打通清洗数据、计算指标、多维分析、可视化呈现、结论汇总。我在实际项目里发现最耗时间的不是画图而是确认口径和清洗脏数据这部分基本占到了70%的工作量。所以建议做任何数据项目时多花时间在设计清晰的口径表和清洗规则上后面所有分析才不会翻车。另外还有一个很容易被忽略的环节结论建议。分析报告如果只是堆砌数据而没有行动建议价值会大打折扣。比如本文中复购率偏低那就应该明确写“建议针对购买一次后 30 天内未回购的用户发放 15 元定向优惠券”这种建议才具有落地意义。最后再分享一个小技巧分析脚本的结构尽量按“读取→清洗→特征工程→指标计算→图表输出”分函数写不要全部堆在一个 jupyter notebook cell 里。函数化之后下次数据一更新直接重新调用pipeline(df)就能自动出新报表。这样省下来的时间足以支撑你每个月再多做两个维度的深度分析慢慢形成一套属于你自己的分析资产。
返回列表