1. 分析环境搭建:从Python安装到Jupyter Notebook
1.1 Python与IDE选型:为什么我最终选了Anaconda
做电商销售数据分析,第一步不是写代码,而是把环境理清楚。很多人一上来就用系统自带的Python,或者随便装一个最新版,结果后面装pandas、matplotlib的时候各种报错,还没开始分析就消耗了大半耐心。
我自己的经历是:早期图省事直接装了官网的Python 3.8,然后手动用pip装库。装到scipy的时候,编译器报了一堆错,最后发现是Windows系统缺了Microsoft C++ Build Tools。那次折腾了整整一个下午,后来直接换成了Anaconda,所有常用的数据科学库一次性装齐,再也没为环境问题头疼过。
如果你也是刚开始接触数据分析,我的建议很直接:装Anaconda,不要装裸Python。原因有三点:
- Anaconda自带conda包管理器,安装、升级、卸载包都更省心,还能创建独立的虚拟环境;
- 它预装了pandas、NumPy、Matplotlib、Jupyter Notebook等绝大多数数据分析必需的库,省去逐个安装的麻烦;
- 自带的Navigator图形界面,对Windows和macOS用户都很友好,不需要记一堆命令行。
这里顺便提一个很多人忽略的版本细节:Python 3.12刚发布的时候,部分第三方库还没有适配,如果因为兼容性问题导致库装不上,可以考虑用Python 3.10或3.11的Anaconda版本,稳定性更高。
安装流程比较简单:去Anaconda官网下载对应你操作系统的安装包,Windows用户注意选择64位版本,安装时勾选“Add Anaconda to my PATH environment variable”,这一步能让后续在命令行里直接使用conda命令。macOS用户安装完后,在终端里执行conda --version验证安装结果。
说到“python环境变量的配置”,这其实是个经典问题。很多入门者装完Python后,在命令行输入python却提示“不是内部或外部命令”,就是因为没有把Python目录加入系统PATH。Anaconda安装时勾选了PATH选项后,这个问题基本就不会再遇到了。
1.2 核心数据处理库:pandas、NumPy、Matplotlib的分工与安装
电商销售数据分析涉及数据读取、清洗、聚合、统计和可视化几个环节,每个环节都有对应的主力库。用一个厨房来做类比的话:
- NumPy 像是基础的刀具和砧板,提供了多维数组对象和大量数学函数,是底层计算的核心;
- pandas 像是灶台和锅具,它的DataFrame结构可以理解为一张电子表格,对行、列、筛选、分组、合并这些操作的支持非常成熟,数据分析中超过70%的代码都在和DataFrame打交道;
- Matplotlib 像是摆盘和装盘,负责把分析结果画成图表,让人能直观地看出趋势和问题。
安装这些库在Anaconda环境下很简单,在命令行或终端里执行:
bash复制conda install pandas numpy matplotlib
如果你用的是原生Python环境,则用pip安装:
bash复制pip install pandas numpy matplotlib
需要提醒的是,数据分析也经常用到seaborn,它是在Matplotlib基础上做了高级封装,画出的图表更美观。安装命令是conda install seaborn或pip install seaborn,我们可以后面按需再装。
1.3 环境验证与项目目录结构
环境装好之后,别忘了做一次快速验证。在命令行输入jupyter notebook,浏览器会自动打开一个工作界面,这算是Jupyter Notebook环境配置成功的标志。如果命令找不到,可能是Anaconda没有正确加入PATH,可以尝试用python -m jupyter notebook启动。
在开始分析之前,我建议先设计好项目目录结构。虽然不一定每个人都要建一整套复杂目录,但预留一个清晰的骨架,会让整个分析过程更有条理:
code复制ecommerce-analysis/
├── data/ # 存放原始数据和清洗后的数据
│ ├── raw/ # 原始导入文件
│ └── processed/ # 清洗后的文件
├── notebooks/ # Jupyter Notebook脚本文件
├── output/ # 图表和导出结果
└── README.md # 项目说明
实际做项目时,把原始数据放进raw目录,清洗后的数据放进processed目录,图表统一输出到output目录,这样无论是自己后续回溯还是别人接手,都能快速定位文件。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据获取:爬数据不是第一步,先想清这三件事
2.1 电商销售数据的常见来源
在写任何爬虫代码之前,有一个问题必须想明白:你手里的数据到底从哪里来?数据获取的合规性和稳定性,远比“能抓到数据”重要。
电商销售数据的常见来源包括:
- 平台导出:淘宝、京东、拼多多等平台的后台,基本都支持导出订单表、商品表、退款表等Excel或CSV文件。这是最正规的途径,也是实际项目中最常用的方式。
- 官方开放API:部分电商平台或数据服务商提供了API接口,经过授权后可以按规则拉取数据。这种方式适合需要长期、定时同步数据的场景。
- 公开数据集和爬虫:公开数据集适合学习和算法竞赛。而通过网络爬虫从公开页面获取信息,需要注意目标网站的robots协议和用户协议,避免涉及个人隐私和商业敏感信息,这在真实项目中是一条不能碰的红线。
我需要明确强调一句:拿爬虫去抓取用户隐私数据或者商业机密数据,是绝对不能碰的事情。 这里讨论的爬虫,只限定在合法的、公开的、非敏感的数据采集场景。
如果你是拿自己的店铺后台数据做分析,最稳妥的方式就是直接导出CSV文件,不需要写爬虫。对于本篇文章,我们假设你已经拿到了一份包含订单号、下单时间、商品名称、商品类目、销售数量、单价、订单金额、收货省份等字段的订单明细表,文件格式为sales_data.csv。这份数据的结构和真实后台导出基本一致。
2.2 用pandas正确读取CSV文件
拿到CSV文件后,第一步是用pandas将其读入内存。这一步看起来简单,但经常有人在这里踩坑,最常见的就是编码问题和中文字段名问题。
python复制import pandas as pd
df = pd.read_csv(
"data/raw/sales_data.csv",
encoding="utf-8", # 如果报错,可以换成 gbk 或 utf-8-sig
dtype={"订单号": str} # 防止订单号被当作数值导致精度丢失
)
关于编码,我多说两句:
- 从Windows平台导出的CSV,很多是
gbk编码,直接用utf-8读取会报UnicodeDecodeError。这时把encoding换成gbk或gb18030即可; - 如果文件里有中文,读取后写回CSV时建议用
utf-8-sig编码。因为Excel默认用ANSI编码打开UTF-8文件时中文会乱码,加了BOM的utf-8-sig可以避免这个问题; dtype={"订单号": str}这个参数很多人会忽略。订单号通常超过15位数字,如果按默认的int64读取,数值精度会丢失,后面再做关联匹配时就会对不上。这是个非常隐蔽的坑。
读入后先做一个简单的数据体检:
python复制print(df.shape) # 查看行数、列数
print(df.columns.tolist()) # 查看所有字段名
print(df.info()) # 查看每列的数据类型和非空值数量
print(df.head()) # 查看前5行数据
print(df.describe()) # 查看数值型字段的统计信息
通过df.info()可以快速看出哪些列有缺失值,哪些列的类型不对。比如下单时间如果是字符串而不是datetime格式,后续的时间分组分析就没法做,等清洗环节再来转换。
2.3 数据字段体检的几个重点
在正式动手清洗之前,花五分钟做一遍字段层面的“体检”,能帮你提前避免很多分析中的隐患。我自己通常会重点关注四个点:
第一,时间字段的格式。 电商后台导出时,下单时间可能是2024-03-15 14:32:08这样规范的格式,也可能是2024/3/15 14:32、20240315这种不统一的格式。通过df["下单时间"].head()抽查几行,基本就能知道大概情况。如果有多种格式混在一起,后面清洗时得统一转换。
第二,数值字段是否有单位或千分位符号。 如果“单价”这一列是"¥19.90"这种带货币符号的字符串,或者销售数量是"1,200"这种带千分位逗号的格式,pandas会将其识别为object类型,无法直接做数值运算。这种情况清洗时会很麻烦,要先把符号去掉再转float。
第三,类目字段是否统一。 同一个商品在不同时期可能被归到不同的类目下,比如“女装-连衣裙”和“连衣裙”其实是同一个东西。后续做类目汇总时,这种不统一会导致分类统计失真。体检阶段可以先打印所有不重复的类目值,核对一遍是否有明显的别名问题。
第四,异常值和极端值。 df.describe()输出里会包含各数值列的最大值、最小值、均值、四分位数等。如果“订单金额”最大值是几百万,而中位数只有几十块,就要警惕是否存在把订单金额和商品单价混填的数据,或者是有测试订单混进来了。
3. 数据清洗:分析结果的可信度全看这一步
3.1 清洗的标准流程:重复值、缺失值、格式统一、逻辑校验
很多人对数据清洗的理解停留在删除空值、去除重复值这两个动作上,实际做电商销售数据分析时,清洗工作要复杂得多。一次完整的清洗至少包含四个环节:
- 重复值处理:删除完全重复的行,或者根据订单号去重;
- 缺失值处理:区分哪些字段的缺失需要补全,哪些字段的缺失必须删除该行;
- 字段格式统一:时间转成datetime,数值去掉符号,字符串去掉首尾空格;
- 逻辑校验:检查金额计算是否正确、时间顺序是否合理、是否存在测试订单等业务层面的异常。
一个完整清洗流程的代码可以这样组织:
python复制# 1. 删除完全重复的行
df = df.drop_duplicates()
# 2. 处理关键字段的缺失值
df = df.dropna(subset=["订单号", "下单时间", "订单金额"])
# 3. 转换时间格式
df["下单时间"] = pd.to_datetime(df["下单时间"], format="%Y-%m-%d %H:%M:%S")
# 4. 去除数值字段中的符号并转成数值类型
df["单价"] = df["单价"].astype(str).str.replace("¥", "").str.replace(",", "").astype(float)
df["订单金额"] = df["订单金额"].astype(str).str.replace("¥", "").str.replace(",", "").astype(float)
# 5. 处理收货省份字段中的空格
df["省份"] = df["省份"].str.strip()
需要特别说明的是,drop_duplicates()默认是对整行所有列进行去重。如果两张不同订单恰好所有字段都一样(比如同一个用户连买了两个一样的商品),这种整行去重是对的。但如果只是订单号相同而其他字段不同的多条记录,就要先弄清楚原因再做去重,否则可能误删有效数据。这个问题的排查思路我会在下一小节详细展开。
3.2 重复值识别:一个订单多条记录的排查链路
在真实项目中,我遇到过一次非常典型的重复值问题:同样的订单号在表里出现了多次,但每次的商品名称和数量不一样。如果不加分辨直接按订单号去重,就会丢失大量信息。
那次的排查链路是这样的:
第一步,先找出重复订单号。 用value_counts()查看哪些订单号的频次大于1:
python复制dup_order = df[df.duplicated("订单号", keep=False)]
dup_count = dup_order["订单号"].value_counts()
print(dup_count[dup_count > 1])
第二步,抽取一个重复订单号的完整记录来看。 比如订单号“DD20240315001”出现了3次,就把这3行全部打印出来,核对每个字段的差异。
通过观察发现,这其实是一个订单对应多个商品的正常情况。用户一次下单买了三件商品,后台导出时按订单明细展开,每个商品一行,订单号自然就重复了。这种情况就不应该去重,而应该保留每一行。
第三步,判断重复的具体形态。 在实际操作中,我习惯用三种维度去快速判断重复的性质:
- 如果所有列都不完全一样,大概率是订单明细展开,保留;
- 如果所有列完全一样,大概率是导出或同步时产生的重复,删除;
- 如果只有个别列不一样(比如退款状态不同),可能是订单发生了状态变更,需要结合业务来判断。
还有一种特殊情况:同一订单号在不同时间段的导出文件里重复出现,可能是跨月文件合并时产生的交集。这种重复需要根据项目需求确定保留哪个版本的记录。
3.3 订单金额逻辑校验:能对上的数据才可信
数据清洗的最后一步,也是很多人最容易跳过的一步,是业务逻辑校验。
电商后台导出的订单金额,和订单明细里的“单价 × 数量”未必完全相等,因为可能存在满减、优惠券、运费等复杂的促销逻辑。但至少有一些基本的数量关系是应该成立的:
- 订单金额不能为负数(除非是退款记录);
- 销售数量不能为0或负数;
- 单价的量级应该合理,比如一件女装几十到几百元是正常的,如果出现0.01元或999999元,需要重点排查。
快速校验方法:
python复制# 查找订单金额为负数的记录
negative_amount = df[df["订单金额"] < 0]
print(negative_amount.shape)
# 查找数量小于等于0的记录
invalid_qty = df[df["销售数量"] <= 0]
print(invalid_qty.shape)
# 校验金额与数量*单价的偏差
df["计算金额"] = df["单价"] * df["销售数量"]
df["金额偏差"] = abs(df["订单金额"] - df["计算金额"])
print(df["金额偏差"].describe())
这里的“金额偏差”字段会揭示一个有趣的现象:很多订单的金额偏差并不为0,而是差个几块钱,这就是优惠券、满减活动的作用。对于这种情况,分析时不能简单地把订单金额修改成单价乘以数量,而要尊重后台导出的订单金额。计算偏差只是为了发现那些偏差极大的异常记录。
我当时做校验时就发现了一类很有价值的异常数据:一批订单的单价是0.01元,数量是几百上千,明显是秒杀活动或刷单记录。如果直接混在正常数据里做分析,日均销量会被严重拉高。处理方法是新建一个“是否参与促销”的标记字段,把这类记录单独标记出来,在分析常规销售趋势时排除,在分析促销效果时单独考察。
4. 销售分析:从总量到结构,找到业务问题
4.1 整体销售走势与月度环比:先看大盘,再谈细节
清洗完之后,就可以开始真正的业务分析了。我自己的习惯是:先看大盘,再看结构,最后看细节。 大盘就是整体销售规模和变化趋势,它能让你快速判断“这段时间业务到底是涨了还是跌了”,有了这个大背景,后面分析任何具体问题才有方向感。
首先建立一个“下单月份”字段,然后按月份汇总销售额:
python复制df["下单月份"] = df["下单时间"].dt.to_period("M")
monthly_sales = df.groupby("下单月份")["订单金额"].sum().reset_index()
monthly_sales.columns = ["月份", "销售额"]
monthly_sales["环比"] = monthly_sales["销售额"].pct_change() * 100
print(monthly_sales)
输出结果大致是:
| 月份 | 销售额 | 环比 |
|---|---|---|
| 2024-01 | 214903.5 | NaN |
| 2024-02 | 189302.8 | -11.9% |
| 2024-03 | 246539.2 | 30.2% |
| 2024-04 | 201847.6 | -18.1% |
| ... | ... | ... |
在解释环比之前,我想先说明一下:为什么这里用“环比”而不是“同比”?因为电商销售受季节性影响很大,比如女装类目每年春夏、秋冬换季都有明显的波峰,如果拿2月和1月比,可能因为春节假期导致销量大幅下滑,但这并不能说明业务变差了。环比适合观察短期变化趋势,而同比(和去年同期比)能剔除季节性因素,更真实地反映业务增长情况。如果在数据量充足、有时间跨年的情况下,建议同时计算两个维度。
从上面的模拟数据里,基本可以看出3月销售额有明显反弹,而4月又回落。接下来要问的问题是:这种波动是整体性的,还是某一个类目带动的? 这就需要按商品类目做拆解分析。
4.2 商品贡献度分析:帕累托图识别核心品类
做电商销售分析的第二个关键视角是商品结构。一个店铺往往有成百上千个SKU,但真正贡献大部分销售额的往往是少数几个核心品类。这就是经典的“二八法则”,在分析工具里常用帕累托分析来呈现。
按类目汇总销售额,并计算累计占比:
python复制category_sales = df.groupby("商品类目")["订单金额"].sum().sort_values(ascending=False).reset_index()
category_sales["销售额占比"] = category_sales["订单金额"] / category_sales["订单金额"].sum() * 100
category_sales["累计占比"] = category_sales["销售额占比"].cumsum()
print(category_sales)
假设输出结果如下:
| 商品类目 | 销售额 | 销售额占比 | 累计占比 |
|---|---|---|---|
| 女装 | 382109.5 | 48.2% | 48.2% |
| 男装 | 183352.2 | 23.1% | 71.3% |
| 童装 | 110012.5 | 13.9% | 85.2% |
| 配饰 | 65470.8 | 8.3% | 93.5% |
| 鞋靴 | 28120.3 | 3.5% | 97.0% |
| 其他 | 23810.6 | 3.0% | 100.0% |
从这个表可以看出,女装一个类目就贡献了将近一半的销售额,女装加男装共同贡献了71.3%,再算上童装,前三名已经贡献了85.2%。这就是典型的“核心品类集中”结构。
对于店铺运营来说,这个分析的直接含义是:应该把运营资源集中投入到女装这个核心品类上,而不是把精力平均分配到所有品类。 同时,对于占比只有3%的鞋靴和其他类目,需要评估是否有继续保留的必要,还是应该收缩战线。
在真实的电商数据分析项目里,帕累托分析还会进一步落到单品层面,因为类目内部SKU的贡献差异可能巨大。核心类目下的爆款单品可能贡献了该类目60%以上的销售额,找到这些单品,后续做库存备货、广告投放时才能有的放矢。
4.3 区域销售分布与用户复购行为分析
除了商品结构,区域分布和用户行为也是电商销售分析的重要维度。
区域分布分析比较简单直接:
python复制region_sales = df.groupby("省份")["订单金额"].sum().sort_values(ascending=False).reset_index()
print(region_sales.head(10))
分析结果往往会呈现出“东部沿海省份销售贡献高、西部内陆省份销售贡献低”的格局。这并不奇怪,因为消费能力和物流覆盖本身就存在地区差异。真正有意思的是:如果把销售额和订单量分开看,会发现某些省份订单量大但客单价低,某些省份订单量小但客单价高。 这对于制定区域营销策略很有参考价值。
举个例子:广东、浙江是订单量和销售额双高的核心区域,适合做重点运营和爆款推广;西藏、青海订单量很少,客单价也不高,如果按订单量排序,它们通常排在最末尾。这种区域差异背后是人口基数、消费水平和物流成本的综合影响,做区域分析时不能只看销售额排名,还要结合物流成本和区域增长潜力一起考虑。
用户复购行为分析稍微复杂一点:
python复制# 建立一个用户维度表,统计每个用户的购买次数和总消费额
user_stats = df.groupby("用户ID").agg(
购买次数=("订单号", "nunique"),
总消费额=("订单金额", "sum"),
首次购买时间=("下单时间", "min"),
最近购买时间=("下单时间", "max")
).reset_index()
# 定义复购:购买次数大于1
user_stats["是否复购"] = user_stats["购买次数"] > 1
# 复购率
repeat_rate = user_stats["是否复购"].mean()
print(f"复购率: {repeat_rate:.2%}")
# 按消费额分层
user_stats["用户分层"] = pd.cut(
user_stats["总消费额"],
bins=[0, 200, 1000, 5000, float("inf")],
labels=["低消费", "中低消费", "中高消费", "高消费"]
)
复购率是衡量店铺用户健康度的核心指标。如果复购率很低,说明用户大多数是一次性消费,店铺长期发展会受到限制。这时候需要进一步分析复购间隔和复购用户的品类偏好,找出推动复购的关键品类。
我当时分析一家服饰类店铺时发现,复购率只有8.5%,处于一个比较低的水平。深入分析后发现,复购用户的首次购买时间集中在换季月份,购买的品类也集中在当季核心款。这个发现说明拉动复购的关键在于“每个季度都要有抓人的新款”,而不是单纯的促销活动。后来运营团队把资源往新品研发和上新节奏上倾斜,复购率在下一个季度提升到了11.2%。
5. 数据可视化:把结论画给业务方看
5.1 图表选型:什么数据配什么图
数据分析结果最终要展示给业务方,而业务方通常没有耐心看一行行的表格数据。这时候可视化的价值就体现出来了。
我在实际项目中总结了一套简单的选图逻辑:
- 时间趋势:用折线图。一条线就能看出销售的涨跌节奏和周期性;
- 类目占比:用柱状图加累计占比曲线(帕累托图),或者用饼图。饼图适合类目数较少的情况,类目太多时建议改用柱状图;
- 区域对比:用条形图,按销售额从高到低排列,一眼就能看出头部区域和尾部区域;
- 用户分层:用柱状图展示各分层用户的数量和消费贡献。
一个值得注意的点是:不要为了炫技使用复杂图表。 三维图、雷达图、动态图虽然看起来很酷,但在实际业务场景中,一张简洁清晰的二维柱状图或折线图往往才是最能传递信息的形式。图表的目的是降低理解成本,而不是增加解读难度。
5.2 用Matplotlib实现三张核心图表
下面我用Matplotlib实现分析过程中最有代表性的三张图。第一张是月度销售趋势图:
python复制import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"] # 解决中文显示问题
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(
monthly_sales["月份"].astype(str),
monthly_sales["销售额"],
marker="o",
linewidth=2
)
ax.set_title("月度销售额变化趋势")
ax.set_xlabel("月份")
ax.set_ylabel("销售额(元)")
ax.grid(True, linestyle="--", alpha=0.5)
plt.tight_layout()
plt.savefig("output/monthly_sales_trend.png", dpi=150)
plt.show()
关于中文字体,这是Matplotlib的一个经典问题。默认字体里没有中文字符,直接画图会出现方框。Windows系统可以指定SimHei或Microsoft YaHei,macOS可以换成PingFang SC或Arial Unicode MS。如果这些字体没生效,可以通过matplotlib.font_manager手动注册字体文件。
第二张是类目占比帕累托图:
python复制fig, ax1 = plt.subplots(figsize=(12, 6))
ax1.bar(category_sales["商品类目"], category_sales["销售额"], alpha=0.7, label="销售额")
ax1.set_xlabel("商品类目")
ax1.set_ylabel("销售额(元)")
ax2 = ax1.twinx()
ax2.plot(
category_sales["商品类目"],
category_sales["累计占比"],
color="red",
marker="o",
label="累计占比"
)
ax2.set_ylabel("累计占比(%)")
ax2.set_ylim(0, 105)
plt.title("各类目销售额贡献(帕累托图)")
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig("output/category_pareto.png", dpi=150)
plt.show()
第三张是区域销售额Top 10的条形图:
python复制top10_region = region_sales.head(10).sort_values("订单金额", ascending=True)
fig, ax = plt.subplots(figsize=(10, 6))
ax.barh(top10_region["省份"], top10_region["订单金额"], alpha=0.7)
ax.set_title("销售额Top10省份")
ax.set_xlabel("销售额(元)")
plt.tight_layout()
plt.savefig("output/region_top10.png", dpi=150)
plt.show()
需要说明的是,这些代码在Jupyter Notebook里运行时,plt.show()会直接在单元格下方显示图片。如果你用的是原生Python脚本文件,图片同样会以弹窗方式展示,运行前确认图形后端配置正确即可。而plt.savefig()一定要放在plt.show()之前调用,否则图形窗口关闭後plt会认为图像生命周期已经结束,保存出来的可能是一张空白图。这也是一个实操中很容易踩的坑。
5.3 可视化顺序:先结论后细节
图表的排列顺序也有讲究。给业务方汇报的时候,第一张图应该是总览性图表,比如月度销售趋势或整体销售漏斗,让对方一眼抓住全局;第二张图是结构性问题图表,比如类目帕累托图,指出销售额集中在哪些类目;第三张图才是细节性问题图表,比如Top10区域、复购用户分层等。
这个顺序背后遵循的逻辑是:先让阅读者看见“发生了什么”,再让他们理解“为什么会这样”,最后才讨论“应该怎么办”。
很多人在做可视化时容易犯的毛病是:一次性把所有图表都贴出来,让业务方自行寻找重点。这样做的效果往往不太好。实际上,分析报告的作用是帮助对方快速提炼结论,而不是把原始信息一股脑抛给对方。我的经验是,每一张图旁边都应该配上一句文字总结,把看图得出的核心判断直接写出来。
6. 项目封装与后续复用:别止步于一次性分析
6.1 用Jupyter Notebook组织分析过程
用Jupyter Notebook做数据分析的好处是:代码块和文字说明可以混排,每一步的操作过程都留下了痕迹。这比纯粹写一个Python脚本要好得多,因为后续回溯分析思路时,Notebook里的Markdown文字能帮你回忆起当时的判断依据。
建议按以下结构组织Notebook:
- 项目说明:写清楚这个分析的目标是什么,数据来源是什么,分析日期是何时;
- 数据导入:读取原始文件,展示数据概况;
- 数据清洗:每个清洗步骤用独立单元格,配合注释说明为什么要这么做;
- 探索性分析:按主题分块组织,比如销售趋势、类目分析、区域分析、用户分析;
- 结论与建议:把分析得出的关键结论写在这里,方便业务方阅读。
这样的Notebook本身就可以充当分析报告,不需要额外再写一份冗长的Word文档。
6.2 销售日报自动化的扩展思路
一次性分析做完之后,还可以考虑把数据分析流程自动化,形成可持续更新的销售日报或周报。
自动化的思路是:把清洗和分析的代码封装成函数,输入是新导出的CSV文件,输出是更新后的报表和图表。可以利用Python的定时任务库,让它在每天早上自动执行:
python复制def generate_sales_report(csv_path="data/raw/sales_data.csv"):
# 读取数据
df = pd.read_csv(csv_path, encoding="utf-8", dtype={"订单号": str})
# 清洗
# 分析
# 生成图表
# 输出结果
pass
在实现自动化之前,有一个关键问题需要考虑清楚:数据源是否稳定。 如果每天都需要人工从电商后台导出CSV,所谓自动化只是省了分析和出图的步骤,数据获取仍然需要人工介入。更彻底的自动化是通过官方API对接,定时从接口拉取数据,但这需要平台开放相应的接口权限,并且要处理接口鉴权和限流等细节。
对于个人项目或中小店铺来说,最务实的方案是“半自动”:人工导出CSV文件放到指定目录,脚本自动完成剩余的分析和报表生成。这种方式既不需要复杂的API对接,也能大幅提升日常效率。
6.3 已踩过的坑与后续扩展方向
最后分享一下我在实际项目中积累的几条经验,也算是对整个分析流程的一个补充。
坑一:Excel打开CSV导致日期格式被改写。 早期我做数据采集时,习惯先用Excel打开CSV做人工检查,然后保存关闭。第二次用pandas读取时,发现时间字段的格式变了,部分日期变成了03/15/2024这种格式,还有一部分变成了Excel自带的序列号数字。后来我养成了习惯:原始数据永远保留一份未经Excel改动的副本,所有人工检查都在副本上进行。
坑二:字段名大小写和空格问题。 电商后台导出的字段名有时候会带上空格,比如“订单金额 ”和“订单金额”是两个完全不同的列名。虽然这听起来很低级,但实际项目中确实会反复遇到。所以清洗代码里最好有一个步骤:
python复制df.columns = df.columns.str.strip()
坑三:过早删除数据。 很多人清洗的时候习惯把异常数据直接删掉,后面发现某个分析需要包含这些数据时,只能重新导入。我的建议是:清洗和过滤操作尽量通过新增字段标记来实现,而不是物理删除。 比如把异常记录标记为is_valid=False,分析时用df[df["is_valid"]]筛选,需要的时候还能把异常数据拉回来复查。
关于后续扩展,比较有价值的方向有:
- 预测分析:基于历史销售数据,用时间序列模型(比如Facebook Prophet算法框架)预测未来一个月的销售额,为备货提供参考;
- 用户画像:结合用户的复购行为、消费金额、购买品类偏好,给用户打标签,输出高价值用户名单;
- 价格弹性分析:分析价格变动和销量之间的关系,帮助定价决策。
这些方向每一块都可以单独展开成一篇完整的项目,但基础都是前面讲到的数据获取、清洗和分析步骤。底子打好了,后面做任何扩展都会事半功倍。
