ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Python电商销售数据分析实战:从Excel清洗到客户分层完整流程

Python电商销售数据分析实战:从Excel清洗到客户分层完整流程 实战用Python分析某电商销售数据前几天收到一位做电商的朋友发来的数据文件是一家店铺过去两年的订单明细说想让我帮着看看“卖得怎么样”。我打开一看就是一个很典型的Excel订单表几千行、十来列有订单号、下单时间、商品名称、类目、数量、单价、实付金额还有客户ID和收货省份。说实话这种活我接过不止一次了。你要是直接甩给老板看原始数据老板只会觉得你什么都没干但如果你用Python把这份表清洗、拆解、算清楚几个关键指标再画几张像样的图整个事情的性质就完全不同了——从“有一堆数据”变成“有结论、有依据、能指导下一步动作”。这篇文章就是完整的实操记录包含了我拿到这份电商销售数据之后从环境准备、数据清洗、指标拆解、商品分析、客户分层到最终生成Excel报告的全过程。不管你是刚学Python的新手还是已经写过一些代码但没跑过一个完整分析项目的同学照着这份流程走一遍基本就能掌握电商场景下数据分析的完整套路。期间踩过的坑、容易出错的地方、老板真正关心的问题我都会一条一条给你说明白。1. 拿到销售数据先想清楚要回答什么问题1.1 原始数据长什么样朋友发来的文件叫销售明细_2024_2025.xlsx我用pandas读进来以后先看了前几行结构大致是这样的字段名示例说明订单编号DD20240101001每个订单唯一编号下单时间2024-01-01 14:23:05订单创建时间商品IDP10023商品唯一标识商品名称便携榨汁杯商品全名类目小家电商品所属类目数量2下单件数单价89.00商品标价实付金额169.10订单实际支付金额客户IDC88617下单用户标识收货省份广东省收货地址省份这种表结构是电商订单分析里最常见、最基础的形式。所有你想知道的经营情况——卖了多少钱、哪些商品好卖、哪些地区贡献高、客户复购怎么样——都能从这十来列里计算出来。分析的第一步不是写代码而是把这张表的业务含义先吃透。1.2 把老板的问题翻译成数据问题朋友原话是“帮我看看我们店卖得怎么样”。这句话听起来很笼统但落到数据分析层面可以拆成四个具体问题整体经营情况销售额、订单量、客单价、退款或异常订单占比是多少趋势变化哪个月卖得最好这个月比上个月是涨还是跌和去年同期比是涨还是跌商品结构哪些商品贡献了大部分销售额哪些类目卖得好价格在什么区间的商品更受欢迎客户质量新客多还是老客多高价值客户占多少多少客户只买过一次这就是数据分析里常说的“业务理解”。很多人一拿到数据就直接pd.read_excel然后开始各种操作这是最忌讳的。你先得知道自己要回答什么问题再决定后面怎么做清洗、怎么建指标、出什么图。否则很容易陷入一个尴尬的境地分析做了一堆老板问一句“所以呢”你答不上来。1.3 环境准备装好Python和依赖库如果你是完全的新手我建议直接用Anaconda里面自带Python解释器和Jupyter Notebook省去不少配置的麻烦。如果你的电脑上已经装好了Python那直接在终端里执行下面几行就行pip install pandas openpyxl matplotlib这次我用到的库只有三个pandas负责数据处理matplotlib负责画图openpyxl是pandas读写Excel时的底层引擎。如果你的Excel文件特别大或者需要做更炫的交互图表可以再加一个pyecharts但对于分析来说这三个库完全够用了。我习惯把项目文件放在一个专门的目录里比如D:/project/sales_analysis然后把Excel文件也放进去。这样写代码的时候路径短不容易出错。在Jupyter Notebook里我第一步固定是这么做的import pandas as pd import matplotlib.pyplot as plt # 让matplotlib可以正常显示中文 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False df pd.read_excel(销售明细_2024_2025.xlsx) print(df.shape) df.head()这里有两个很关键的小细节。第一plt.rcParams[font.sans-serif] [SimHei]是必须的否则中文标签在图上全部显示成方框。第二df.shape能快速告诉你数据规模比如我的输出是(26940, 11)说明有两万六千多行、十一列量不算大单机处理完全没压力。先确认数据规模再继续操作是一个特别好的习惯。2. 读数据之前先把脏数据的坑排掉2.1 pandas读取Excel的常见问题如果你用的是Jupyter Notebook第一次执行pd.read_excel经常遇到各种问题。最常见的是ModuleNotFoundError: No module named openpyxl原因是电脑上只装了pandas没装openpyxl。上面的pip install openpyxl已经解决了这个问题。还有一个容易让人头疼的是路径问题。Excel文件名直接带中文没问题但如果文件放在别的盘符且路径里有中文在Windows下容易出编码或者路径解析问题。我的建议是把数据文件复制到项目目录下用相对路径读取这样最稳妥。如果Excel里有多个Sheet或者表头在第一行但前几行是一些说明文字可以这样处理df_raw pd.read_excel( 销售明细_2024_2025.xlsx, sheet_name订单明细, header0 )2.2 处理缺失值、重复订单和异常金额读取完成之后第一件事是检查数据质量。我常用的套路是三连看看缺失、看重复、看类型。# 1. 缺失值概览 print(df_raw.isnull().sum()) # 2. 重复订单检查 print(df_raw.duplicated(subset[订单编号]).sum()) # 3. 列类型概览 print(df_raw.dtypes)这份数据里客户ID有零星的缺失大约30行左右只占总量千分之一对整体分析没有实质影响我选择了直接删除商品名称和类目没有缺失类型也整齐。重复订单检查很重要有时候系统导出时会多算一遍或者有同一个订单编号出现了两行如果不处理销售额会被虚增。检查下来这份数据没有重复算是比较干净的。异常值方面重点看实付金额。这里就发现了一个问题有一小部分订单的实付金额是负数数量大概是订单金额的0.5%。一看就是售后退款或者部分退款的订单记录因为系统把这些订单的金额做了反向记录。这种数据如果不处理会直接扭曲整体销售额。处理逻辑有两个选择一是直接过滤掉理由是我们只关心真实成交订单二是保留并单独分析售后占比。为了给朋友一个全面的视角我用过滤的方式生成了“成交订单”数据同时把负金额订单记成一个标记字段。df df_raw.copy() df[订单状态] df[实付金额].apply(lambda x: 正常 if x 0 else 退款/负单) df_valid df[df[实付金额] 0].copy()2.3 字段类型清洗和时间特征抽取字段类型的问题主要集中在下单时间。读取的时候pandas通常会把时间列识别成字符串或者datetime对象但有时候会出现下单时间显示成类似2024-01-01 00:00:00的情况。稳妥起见我直接用pd.to_datetime强制转换df_valid[下单时间] pd.to_datetime(df_valid[下单时间])转换之后顺手把日期维度的特征全部拆出来这会让后面的趋势分析方便很多df_valid[年] df_valid[下单时间].dt.year df_valid[月] df_valid[下单时间].dt.month df_valid[日] df_valid[下单时间].dt.day df_valid[星期] df_valid[下单时间].dt.weekday # 0周一 df_valid[小时] df_valid[下单时间].dt.hour df_valid[年月] df_valid[下单时间].dt.to_period(M)这里to_period(M)的作用是把时间压缩成“某年某月”的格式方便按月汇总。小时和星期字段在后面的时段分析、一周销售规律里非常有用。做完这些清洗工作我得到了一个干净的df_valid大约有两万六千多行有效订单。接下来才进入正式分析阶段。3. 销售大盘先看整体趋势和关键指标3.1 核心指标怎么算电商分析里最基础的四个指标销售额、订单量、客单价、件单价。用pandas一行就能算完total_sales df_valid[实付金额].sum() # 总销售额 total_orders df_valid[订单编号].nunique() # 总订单数 total_items df_valid[数量].sum() # 总销售量 unit_price total_sales / total_items # 件单价 avg_order total_sales / total_orders # 客单价 print(f总销售额: {total_sales:.2f}) print(f总订单数: {total_orders}) print(f总销售量: {total_items}) print(f客单价: {avg_order:.2f}) print(f件单价: {unit_price:.2f})我这份数据算出来的结果是两年总销售额约317万元、订单量8062单、销售件数约1.6万件、客单价约393元、件单价约196元。客单价393元说明这家店卖的不是9块9包邮的便宜货而是客单价中等的家居生活类商品。这些数字本身很重要但更重要的是看它们的变化趋势。3.2 用同比和环比看趋势单看一个总销售额是没有意义的老板更在意的是“最近卖得好不好”。所以第二步是按月汇总数据做一个逐月趋势表monthly df_valid.groupby(年月).agg( 销售额(实付金额, sum), 订单量(订单编号, nunique), 销售量(数量, sum) ).reset_index() monthly[客单价] monthly[销售额] / monthly[订单量] print(monthly.head())有了这个逐月汇总表之后我还顺手算出了“环比增长率”和“同比增长率”。环比就是和上个月比同比就是和去年同一个月份比。这两个概念老板可能不熟悉但一解释就懂环比看出短期波动同比排除季节性因素看长期趋势。实际算出来有一个非常明显的信号2024年11月和12月销售额明显高于其他月份2025年大促月份的销售额甚至翻了一倍。这说明这家店的销售季节性非常强大促节点双11、双12或者店庆日对业绩拉动巨大。我把这个发现放在分析结论的第一条——季节性营销策略确实有效应该在每年大促前备好库存和投放预算。3.3 一天里哪个时段成交最多除了月度趋势我还做了小时维度的分析。把订单按小时分组看看一天24小时里哪些时段成交量最高hourly df_valid.groupby(小时).agg( 订单量(订单编号, nunique), 销售额(实付金额, sum) ).reset_index()结果挺有规律每天有两个小高峰——上午10点到12点晚上20点到22点晚上的峰值明显高于白天。这种数据对店铺运营其实很有参考价值。比如客服排班可以重点覆盖这两个高峰时段上新活动、优惠券发放的时间也可以安排在这些时段更容易带动转化。4. 商品和类目找出真正赚钱的品4.1 类目贡献度分析二八法则藏在数据里看完整盘数据接下来该拆商品了。我的习惯是先看类目再看单品。类目维度能告诉老板“哪条产品线是主力”。用groupby按类目汇总算出销售额和订单量然后算每个类目占总销售额的比例category_sales df_valid.groupby(类目).agg( 销售额(实付金额, sum), 订单量(订单编号, nunique), 销售量(数量, sum) ).sort_values(销售额, ascendingFalse).reset_index() category_sales[销售占比] category_sales[销售额] / category_sales[销售额].sum() * 100 category_sales[累计占比] category_sales[销售占比].cumsum()这份数据里排名前两位的类目贡献了接近七成销售额前三个类目贡献超过八成。这就是很标准的二八法则20%的类目贡献80%的业绩。看到这种结果建议老板把注意力集中在前几个类目上后边的长尾类目维持基本运营就行不用花太多精力。4.2 价格带分布搞清楚你的东西卖给谁单看类目还不够我继续把商品按照“单价”做价格带分析。这里的核心问题是店铺的销售额到底靠大量低价走量还是靠少量高价赚钱操作上可以用pd.cut给商品价格分组:bins [0, 50, 100, 200, 300, 500, 1000, 10000] labels [0-50, 50-100, 100-200, 200-300, 300-500, 500-1000, 1000] df_valid[价格带] pd.cut(df_valid[单价], binsbins, labelslabels, rightFalse)统计后发现一个有意思的现象销量最大的价格带是100-200元但销售金额最大的价格带是300-500元。也就是说店铺既有走量的中低价品也有能拉高销售额的中高价位品。这种结构其实是比较健康的不会因为低价竞争失去利润也不会因为高价段销量不足导致整体销售过于依赖小部分订单。4.3 找出销量和销售额的“双料冠军”类目和价格带是从面看问题最后要落到具体的单品。我按商品ID和商品名称做单品维度汇总分别算销售额、订单量、销售量、客单商品价然后同时按销售额和销售量排序各抽出前10名。实际数据里出现了一个非常典型的电商现象销售额排名第一的单品和销售量排名第一的单品并不是同一个。销量最高的是个59元的便携收纳盒卖了近两千件但销售额最高的是一个399元的多功能料理锅光这一件单品就贡献了几十万元销售额。这就是所谓的“引流款”和“利润款”的区别。老板在做选品决策时引流款负责拉新和维护店铺热度利润款负责赚钱。我把这两个维度交叉做了一个散点图横轴是销售量纵轴是销售额每件商品是一个点。落在右上角的商品既是爆款也是利润担当是运营的重中之重右下角的商品是走量但利润不高的大概率是引流款左上角的商品可能单价高但走量一般属于利润款但需要更多流量扶持。这种图一画出来品类策略就很直观了。4.4 涨跌最快的商品除了静态排名动态变化也很重要。我针对2025年和2024年都有销售记录的同一批商品分别计算出两年销售额的同比增长率筛选出了涨幅前10名和跌幅前10名。这个分析是为了发现潜力新品和退坡老品。涨幅榜里有一些是2025年刚上市的新品前三个月销量平平后来增长非常猛比如一款“便携随行杯”2025年下半年销售额比上半年翻了近三倍。跌幅榜里则有一些以前卖得好、最近逐渐没动静的品比如一款老款的保温壶同比销售额直接腰斩。这种信息对库存管理和采购计划非常有用该补货的补货该清仓的清仓别再一个劲儿给老品投广告了。5. 客户价值RFM和复购分析没那么玄5.1 从订单表还原客户维度表订单明细是“每一行是一笔订单”但客户分析需要的是“每一行是一个客户”。这个转换在pandas里就是一次groupbyrfm df_valid.groupby(客户ID).agg( 最近购买时间(下单时间, max), 购买频次(订单编号, nunique), 消费总额(实付金额, sum) ).reset_index() rfm[最近购买时间] pd.to_datetime(rfm[最近购买时间])这三列分别对应RFM模型里的三个维度RRecency最近一次购买时间距今多久、FFrequency购买频次、MMonetary消费总额。RFM模型是客户分层最经典、最实用的方法不涉及任何复杂的机器学习算法核心就是按这三个维度把客户分成几类然后对不同类型采取不同运营策略。5.2 用RFM做客户分层具体打分逻辑是把每个客户的三项指标分别和所有客户的中位数比较高于中位数记为1分低于中位数记为0分。这样每个客户得到一个三位编码比如“111”就是三项都高属于高价值客户“100”说明最近买过但消费频次和金额都不高。r_date rfm[最近购买时间].max() rfm[R] (rfm[最近购买时间] - r_date).dt.days rfm[R_score] rfm[R].apply(lambda x: 1 if x rfm[R].median() else 0) rfm[F_score] rfm[购买频次].apply(lambda x: 1 if x rfm[购买频次].median() else 0) rfm[M_score] rfm[消费总额].apply(lambda x: 1 if x rfm[消费总额].median() else 0)说明一下R值本身是“距离上次购买过去了多少天”所以R值越小代表越近购买逻辑上和F、M相反阈值判断写成“小于等于中位数给1分”。打完之后把编码映射为业务标签111高价值活跃客户是最优质的用户。101、011有潜力客户可能消费不高但活跃或频次高但金额低。100、010、001一般客户有一定活跃度但价值一般。000沉默/流失客户很久没来、买得少、金额低。统计下来最让我注意的是这家店有接近38%的客户属于“000沉默客户”。也就是说两年里只有不到四成的客户购买过一次以上但“111高价值客户”数量虽然只占5%却贡献了将近25%的总销售额。这就是客户分层的力量——你用一小部分人撑起了大半个生意。运营上应该重点服务这些高价值客户比如给他们发专属券、做回访、给老客专享价。5.3 复购行为有多少人买完第二次RFM已经包含了购买频次的信息但我还是单独算了一个更直观的指标复购率。口径是“两年内购买次数在2次及以上的客户占比”。customer_stats df_valid.groupby(客户ID)[订单编号].nunique() repurchase_rate (customer_stats 2).mean() print(f复购率: {repurchase_rate:.2%})这家店的复购率大约27%。电商行业里复购率如果是20%-30%算是中等水平还有提升空间。复购率高的本质不是靠拉新而是靠产品力和“买了之后还想再买”的体验。我建议老板重点看看那些买了1次之后在1-2个月内又买了第2次的客户分析他们二次购买的商品组合看看是否存在“连带购买”的规律。比如买了料理锅的客户半年内是不是大概率还会再买一套替换配件如果有这个规律就可以在下单后做关联推荐这是复购率最直接的拉升手段。6. 可视化与输出让老板一眼看懂结论6.1 三张最有说服力的图分析做得再好最后要让人看得懂、记得住。我这次一共画了三张核心图每张对应一个核心结论。第一张是月度销售额折线图。横轴是年月纵轴是销售额直接描绘出这个店铺的销售节奏。折线图上大促月份的两个尖峰非常明显一眼就能看出整家店的销售规律。plt.figure(figsize(10, 4)) plt.plot(monthly[年月].astype(str), monthly[销售额], markero) plt.xticks(rotation45) plt.title(月度销售额趋势) plt.tight_layout() plt.show()第二张是类目销售额占比的条形图。横轴是类目、纵轴是销售额按降序排列前几个长条和后面几个短条形成鲜明对比二八法则一目了然。第三张是客户分层占比的饼图或条形图。横轴是标签分组纵轴是客户数量占比再叠加上每一组的销售额占比。你一下就能看到“少数人贡献多数钱”的结构。图表讲究的是信息密度一张图讲清楚一个结论就够了。不要在一张图里塞太多维度老板看了反而迷糊。6.2 把结果写成带多Sheet的Excel报告分析结果最终要以一种别人能直接使用的方式交付。我习惯生成一个Excel报告把不同的分析结论放在不同Sheet里再在第一个Sheet写一页“核心结论”和“建议动作”。生成方法是用pd.ExcelWriterwith pd.ExcelWriter(销售分析报告.xlsx, engineopenpyxl) as writer: monthly.to_excel(writer, sheet_name月度趋势, indexFalse) category_sales.to_excel(writer, sheet_name类目分析, indexFalse) item_sales.to_excel(writer, sheet_name商品TOP50, indexFalse) rfm.to_excel(writer, sheet_name客户分层, indexFalse)这里engineopenpyxl是必须的因为pandas默认的Excel写入引擎可能不支持xlsx格式。跑完之后在项目目录里会生成一个销售分析报告.xlsx老板拿到手就能自己翻各个Sheet看结果。6.3 常见报错与排查速查表最后把这次项目里遇到过的、以及以前其他项目里容易出现的报错整理一下方便后面自己排查问题现象原因解决办法图表中文显示为方框matplotlib默认字体不支持中文设置plt.rcParams[font.sans-serif] [SimHei]读取Excel报ModuleNotFoundError缺少openpyxlpip install openpyxl日期列变成字符串无法按月聚合读取时类型没有被自动识别用pd.to_datetime()强制转换实付金额出现负数包含退款/负向订单记录单独标记或过滤再分析成交订单写入Excel报PermissionError目标文件被打开占用关闭Excel文件后重跑数据量大导致运行卡顿DataFrame内存占用过高用df.info()查看类型把不需要的列drop掉7. 写在最后的实操心得这次分析完整走下来我个人最深的体会是数据分析项目的成败三分在技术、七分在业务理解。技术层面无非是pandas那一套groupby、merge、pivot_table的组合练几次就能熟真正的差距在于你懂不懂老板问那个问题的背后意图你知不知道哪些数据是有水分的你能不能从一堆数字里提炼出一句人话——“你店里38%的销售额来自5%的老客户所以运营重点应该是维护老客而不是一味拉新。”这句话的价值比任何一张表都高。有一个小技巧是我自己做项目总结时必用的分析完数据之后强制自己写一个“如果只能给老板提三个建议”的清单。如果这个清单能写出来说明你的分析逻辑是完整的如果写不出来说明你还没想透。这个习惯帮我从纯技术上手变成了真正能帮业务做决策的人。希望你做完这份分析之后也试着这样要求自己一步。
返回列表