去年接了一个电商数据分析的小活,对方丢给我一份订单数据,说“你帮我们看看今年的销售到底怎么回事”。这个需求听着简单,但真正做起来远不是跑一条 sum() 就交差的事。我全程用Python把数据清洗、指标计算、可视化梳理了一遍,踩了不少坑,也总结出一套可以复用的分析流程。这篇博文我就把这个“用Python分析某电商销售数据”的实战过程完整写出来,包括每一步为什么要这么做、代码怎么组织、遇到问题怎么排查,给想入门数据分析或者准备接手类似任务的朋友一个可以直接照着操作的最小闭环。
先说结论:整份订单数据有17万多行,12个字段,涉及约3万用户和2000多个商品。我用pandas完成清洗和聚合,用matplotlib完成图表输出,最终产出了月度销售趋势、品类占比、Top10商品榜、用户复购率四个核心分析结果,还顺手发现了几个数据质量问题,这些质量隐患如果不处理,后面的结论全部会失真。整个过程大概花了一天,其中真正跑分析只占两三个小时,剩下时间全部花在“数据长什么样”和“为什么这里有脏数据”这两件事上。项目适合有一点点Python基础、想实战数据分析的读者,也适合运营、产品同学拿去理解分析师的日常工作逻辑。
1. 分析目标与整体设计:动手前先想清楚这几件事
1.1 先搞清楚业务到底要什么答案
很多新手拿到数据的第一反应是打开Jupyter就开始敲 df.head(),然后东看一眼西看一眼,最后写了两三百行代码却不知道核心结论是什么。我的习惯相反,先花30分钟和需求方确认三个问题:给谁看、看什么、看完要做什么决策。
这次需求方的运营负责人只关心四件事:第一,今年整体卖了多少,和去年比是涨是跌;第二,哪些商品撑起了销售大盘,哪些类目在拖后腿;第三,用户是一次性买卖多还是复购多,有没有忠诚用户群体;第四,能不能从数据里看到明显的淡旺季规律,方便后续备货和排活动。
确认完这些问题,分析框架就清晰了:
| 分析方向 | 要回答的业务问题 | 核心指标/方法 |
|---|---|---|
| 销售大盘 | 卖了多少、客单价如何 | GMV(成交总额)、订单量、客单价(AOV) |
| 时间趋势 | 淡旺季、增长放缓时间段 | 月度聚合、同比/环比 |
| 商品结构 | 哪些商品赚钱 | Top10商品、类目GMV占比 |
| 用户行为 | 用户是否愿意重复购买 | 复购率、购买频次分布 |
目标一旦定了,后面的所有代码都有明确指向,而不是漫无目的地“分析”。
1.2 为什么选Python这套技术栈来处理
这份数据是CSV格式,大概有60多MB,Excel直接打开会卡,用SQL也行,但考虑到数据文件是对方从后台导出的,需要大量清洗和探索性分析,Python可以说是最优解。
我在电商数据分析场景里最常用的是pandas、numpy、matplotlib三个库。pandas处理表格型数据非常顺手,类似Excel但比Excel灵活得多,尤其是分组聚合、透视、时间序列重采样这些操作,写一行代码就能完成。numpy负责底层数组计算,很多pandas操作底层依赖它,装上不亏。matplotlib是可视化基础库,虽然画出来的图表默认样式有点朴素,但胜在可控性强,而且它是seaborn、plotly这些库的地基,先掌握它再扩展其他可视化库会轻松很多。
这套组合最大的优势不是某个库多强,而是它们之间的数据流是无缝的。pandas算完的结果可以直接喂给matplotlib,不用像Excel那样频繁地手动复制选择区域。对分析这种需要反复试错的场景,代码化的好处是全部过程可复现,参数可修改,今天跑一遍,明天换数据再跑一遍就行。
1.3 分析代码的组织方式:脚本和Notebook怎么分工
数据分析任务的分工方式很多人不重视,实际影响却不小。我的建议是:探索阶段用Jupyter Notebook,写正式分析脚本用纯.py文件。
Notebook的交互特性非常适合逐段验证,比如清洗某列后立刻看结果、画完图立刻调整参数,思维是流动的。但Notebook也有很坑的地方:执行顺序容易乱,比如你删掉中间某个cell重新运行,后面的cell可能还在用旧的变量,结果就会出错且不易察觉。所以我通常是在Notebook里做好探索验证,确认所有逻辑没问题后,再把核心代码整理成一个结构清晰的analysis.py,按顺序执行,这样可维护性最强,也方便交接给别人。
脚本文件内部我会按功能分成几个区块:数据加载、数据清洗、特征构造、指标计算、可视化输出。每个区块间用函数封装,减少变量互相污染。后面所有实战内容,我都按这个思路来讲解。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备:一套能避免80%报错的Python配置
2.1 Python版本和虚拟环境选择
在开始写任何分析代码之前,先把环境配置好。数据分析场景建议使用Python 3.10及以上版本,pandas和matplotlib对新版本支持都很及时,没必要守在老版本上给自己添麻烦。Windows、macOS、Linux三平台下安装Python的方式有些差异,但核心要点是一致的。
一个很容易踩坑的点是:很多电脑上装了多个Python版本,直接在终端敲python不一定是你想用的那个解释器。为了杜绝这个问题,我强烈建议每个项目单独建虚拟环境。虚拟环境相当于给项目开了一个独立的小房间,里面的Python版本和第三方库互不干扰,不会出现“A项目要pandas 1.5,B项目却把pandas升到2.0把A搞坏”的事故。
实测下来最顺手的方式是用Python自带的venv模块:
bash复制# Windows
python -m venv .venv
# macOS / Linux
python3 -m venv .venv
创建完成后,激活环境再装依赖:
bash复制# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
# 激活后安装本项目需要的库
pip install pandas numpy matplotlib jupyter
如果你用Anaconda或者Miniconda,也可以用conda create -n ecommerce python=3.10这样的方式建环境。原理一样,都是隔离依赖。我用venv是因为它不需要额外装软件,且项目配好requirements.txt后,换机器时执行pip install -r requirements.txt就能一键复现环境,协作成本低。
2.2 IDE与编辑器的配置要点
编辑器方面,VSCode和PyCharm是最主流的两个选择。PyCharm的社区版免费,但专业版才有的很多功能对数据分析来说其实非必需。我自己长期用VSCode,原因一是启动快、插件生态好,二是直接支持Jupyter Notebook文件,三是调试Python代码体验很不错。
VSCode配置Python环境有几个关键动作,很多新手卡在“明明安装好了Python,但代码里报找不到模块”。
第一,安装官方Python扩展,微软出的那个。第二,在左下角或命令面板(快捷键Ctrl+Shift+P)输入“Python: Select Interpreter”,选择你刚创建的虚拟环境里的Python解释器,千万别用系统默认解释器,否则环境白建了。第三,终端里要确认当前激活的是虚拟环境,看命令行前面有没有(.venv)标识。
上面这些配置做完,你会发现之前那些ModuleNotFoundError基本消失,因为解释器选对了,pandas装在哪、从哪import都清楚了。
2.3 导入库与全局参数设置
分析工作开始前,我会统一导入需要用到的库,并设置几个全局参数。这些参数写一次,后面所有代码块都生效:
python复制import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 让图表支持中文显示
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "Arial Unicode MS"]
plt.rcParams["axes.unicode_minus"] = False
# pandas显示设置,避免字段太多时被省略号截断
pd.set_option("display.max_columns", 50)
pd.set_option("display.width", 200)
print("pandas版本:", pd.__version__)
print("numpy版本:", np.__version__)
axes.unicode_minus这个参数很多人会漏掉,不设置的话图表里的负号会显示成方块。中文字体那行我后面在可视化章节还会详细讲。
3. 数据清洗:质量不过关,分析就是白做
3.1 第一步先摸清数据结构
拿到数据后不要马上算指标,先做三件事:看形状、看字段类型、看前几行内容。这次订单数据文件的字段设计很典型,我改成通用命名后大概是这个结构:
| 字段名 | 含义 | 类型 |
|---|---|---|
| order_id | 订单号 | 字符串/整型 |
| order_date | 下单时间 | 字符串(形如2024-01-15 13:22:08) |
| user_id | 用户ID | 整数 |
| product_id | 商品ID | 整数 |
| product_name | 商品名称 | 字符串 |
| category | 商品类目 | 字符串 |
| quantity | 购买数量 | 整数 |
| unit_price | 单价(元) | 浮点数 |
| total_amount | 订单实付金额(元) | 浮点数 |
| payment_status | 支付状态 | 字符串 |
| province | 收货省份 | 字符串 |
| channel | 下单渠道 | 字符串 |
用pandas读入后,先跑一段基础侦察代码:
python复制df = pd.read_csv("orders.csv", encoding="utf-8")
print("数据形状:", df.shape)
print("字段列表:")
print(df.columns.tolist())
df.head()
数据形状会告诉你数据量规模,比如这次是(172345, 12),意味着有17万行、12个字段。接着看df.info(),它能把每个字段的非空数量、数据类型一次性展示出来,比肉眼一个一个查高效得多。我用df.describe()看数值型字段的分布,重点观察total_amount这种关键金额字段的均值、分位数、最大最小值,判断是否存在明显离群值。
3.2 处理脏数据的几种典型情况
先从真实项目里最常见的三类脏数据说起:缺失、重复、逻辑异常。
缺失值处理要分case看。我先用df.isnull().sum()统计每列缺失数量。这次数据里province缺失了324行,order_id没有缺失,total_amount缺失了17行。province缺失不影响销售总体的分析,但如果你是做地区销售分析,就要决定是删掉这324行还是填“未知”。total_amount缺失则不能轻视,金额是核心指标,缺失原因很可能是订单状态异常,我直接删掉并且记录日志。
重复值要特别注意“看似重复实则不是”的情况。同一个订单可能包含多个商品,订单号会重复,这不算需要删除的数据。真正的重复是指整行所有字段都一样,这种通常是数据导出或同步机制导致的冗余,可以删除:
python复制print("完全重复行数:", df.duplicated().sum())
df = df.drop_duplicates()
这里我提醒一句:做删除前先确认指标口径。如果一份数据存在“一单多商品”,你按order_id去重后得到的是订单数,按行保留得到的是商品明细行数,两个口径都正确,但千万别把两者混着用。
第三类是异常值,也是这次最关键的发现。我在检查total_amount时发现它出现了负值,粗看以为是对应退款记录,但追问后得知这套表是“下单明细表”,退款订单应该已经通过payment_status字段区分开了。于是我把数据按支付状态分组看金额分布,发现已支付订单里居然也有几十笔负金额,这就不是正常业务行为了。处理逻辑写清楚:只有payment_status为“已支付”,且total_amount大于0的记录,才进入销售额统计。这种业务规则不搞明白,后面的GMV算出来都是错的。
3.3 数据类型转换:日期和数字的坑
CSV读进来后,日期是字符串,金额可能是文本或带货币符号的格式。如果直接拿字符串去算时间差或者排序,轻则结果错误,重则直接报错。所以数据清洗必须包含类型转换这一环。
我通常用pd.to_datetime把订单时间转成真正的datetime类型,方便后续按年月日提取、做重采样:
python复制df["order_date"] = pd.to_datetime(df["order_date"], errors="coerce")
errors="coerce"是我最爱用的参数:遇到解析不了的日期,不报错而是置为NaT,方便后面统一排查。转换后我用df["order_date"].dt.date看一眼前几行,确认没有解析错乱。
金额字段有时候会因为带了“元”、“¥”等符号而变成object类型,这时就用pd.to_numeric处理,非法内容置为NaN再统一填充或删除:
python复制df["total_amount"] = pd.to_numeric(df["total_amount"], errors="coerce")
df = df.dropna(subset=["order_date", "total_amount"])
清洗完以后,我会做一次“体检”确认数据质量,形成一张质量报告表,把原始行数、清洗后行数、缺失率、异常值处理数都记录下来。这一步看起来很繁琐,但放到团队协作里特别有价值——数据分析的每一步都可追溯,结果有疑问时能快速定位是在哪个环节出的问题。
4. 核心指标计算与业务洞察
4.1 销售大盘数据:GMV、订单量、客单价
数据清洗完成后,终于可以开始算正经指标了。电商销售分析最核心的三个基础指标是GMV、订单量和客单价。
GMV也就是成交总额,是所有有效支付订单的实付金额求和;订单量是有效支付的订单笔数,注意这里的订单按order_id去重还是按行数算要看口径。客单价(Average Order Value)等于GMV除以订单量,衡量每一单平均能带来多少收入。换算代码如下:
python复制gmv = df["total_amount"].sum()
order_cnt = df["order_id"].nunique()
aov = round(gmv / order_cnt, 2)
print(f"GMV: {gmv:,.0f} 元")
print(f"订单数: {order_cnt:,} 单")
print(f"客单价: {aov:,.2f} 元/单")
值得留意的是nunique()和count()的区别。nunique()统计的是去重后的唯一值数量,订单量应该用去重后的订单号数量,避免一单多商品行被重复算作多单。我当时第一次偷懒用了df["order_id"].count(),结果订单数被虚高了三成,这就是口径不严谨的代价。
4.2 时间维度深度分析:趋势、同比与环比
对电商运营来说,判断增长是真是假,不能只看一个总数,必须看时间趋势。我把下单时间提取成“年月”维度,然后聚合每个月的GMV:
python复制df["ym"] = df["order_date"].dt.to_period("M")
monthly_gmv = df.groupby("ym")["total_amount"].sum()
这里用to_period("M")比dt.month更灵活,to_period("M")得到的是2023-01这种Period对象,天然包含了年份信息,而dt.month只得到月份数字1到12,跨年时分不清。聚合完月度数据后,我会用折线图观察整体走势,同时算一下环比(这个月相比上个月增长了多少)和同比(这个月相比去年同月增长了多少)。
这次的月度趋势图出现了一个极其明显的双峰:一个高峰在6月,一个更高的高峰在11月。结合业务背景,6月是电商大促月,11月更是全年最重的促销节点,属于典型的强季节型销售结构。但要注意的是,促销月GMV高不代表利润高,如果后面能拿到成本和毛利数据,可以继续做促销有效性分析,看看这些大促订单到底赚不赚钱。这就是分析思路要往前延伸的地方。
4.3 商品维度分析:谁在撑起销售额
只告诉老板“11月卖得好”还不够,还得知道卖的是什么东西。商品维度的分析我通常分两个层次:先看单品贡献,再看类目结构。
单品贡献看Top10商品就很直观:
python复制top10 = df.groupby("product_name")["total_amount"].sum() \
.nlargest(10) \
.reset_index()
top10.columns = ["product_name", "gmv"]
print(top10.to_string(index=False))
从结果看,排名第一的单品贡献了约4.8%的GMV,Top10单品合计贡献约28%。头部商品很集中,说明这家店铺的销售严重依赖爆款单品,对运营来说意味着两个风险:一是爆款一旦断货或差评,销售大盘会明显承压;二是头部商品集中也意味着流量运营效率较高。这类对比有个更好的计算方式:算累计占比。把商品按GMV降序排列,对GMV做累计求和,再除以总GMV,就能得到帕累托分析的经典结论——前多少名商品贡献了80%的销售额。
类目层面的分析也不难,用pivot或groupby都能完成:
python复制cat_gmv = df.groupby("category")["total_amount"].sum() \
.sort_values(ascending=False)
cat_share = cat_gmv / cat_gmv.sum() * 100
print(cat_share.round(2).to_string())
三个大类的占比分别是约45%、33%、22%。头部类目占比和Top10单品的结论相互印证,整个大盘的品类集中度偏高,如果类目之间能形成引流款和利润款的搭配,销售结构会更健康。这些结论我最终都落到一页PPT式的可视化里给运营看,他们一下子就抓住了重点。
4.4 用户维度分析:复购率到底怎么算
用户分析里最容易扯皮的就是指标口径,尤其复购率,不同人嘴里说的“复购率”可能根本不是同一个东西。这次我采用的复购率口径是:在统计周期内,购买次数大于等于2次的用户数,除以有购买行为的用户总数。它的含义是有多少买过的人不是“一锤子买卖”。
计算逻辑比较绕,先按user_id分组统计每个用户的购买订单数,再判断订单数是否大于等于2:
python复制orders_per_user = df.groupby("user_id")["order_id"].nunique()
repeated = orders_per_user[orders_per_user >= 2]
total_users = orders_per_user.shape[0]
repeat_users = repeated.shape[0]
repeat_rate = repeat_users / total_users * 100
print(f"活跃下单用户数: {total_users}")
print(f"其中有复购行为的用户数: {repeat_users}")
print(f"用户复购率: {repeat_rate:.2f}%")
最终算出的复购率约为22.7%,也就是每100个用户里大约有23个人会在统计周期内再次购买。低于20%说明复购差,得靠拉新活着;电商行业健康水平通常在30%以上。这家22.7%说明用户黏性偏弱,可以建议运营往会员体系、老客召回机制方向发力。
在算复购率时有个细节:如果同一用户在同一天下了多笔订单,算不算复购?不同业务的答案不一样。如果购买的是快消品、生鲜,一天买两次很正常,算复购也合理;如果是家电、家具这类低频耐用品,同一天买多单大概率是拆单或赠品单,建议剔除。我这次按业务属性把同一天的多笔订单合并成一次购买后再算了一次,发现复购率掉到17.9%,两个口径差距很大,所以复购率的统计方法必须在报告里明确写出来,不能只丢一个数字。
5. 可视化输出:把结论画给老板看
5.1 Matplotlib的中文字体与样式配置
数据分析在分析阶段可以只看数字,但汇报阶段必须可视化。我这次所有图表都用matplotlib完成,因为它在Python生态环境里兼容性最好,且逻辑透明。
matplotlib默认是不支持中文的,直接画图会出现一个个方框乱码。解决方法是把字体指定为系统中存在的中文字体。Windows下常见的SimHei(黑体)和Microsoft YaHei(微软雅黑)都能用,macOS下一般用Arial Unicode MS或PingFang SC,Linux发行版则需要先安装中文字体再指定字体名。
一个稳妥的做法是写个函数,按系统自动选择可用字体:
python复制import matplotlib.font_manager as fm
def set_chinese_font():
candidates = ["Microsoft YaHei", "SimHei", "PingFang SC",
"Arial Unicode MS", "Noto Sans CJK SC"]
available = {f.name for f in fm.fontManager.ttflist}
for font in candidates:
if font in available:
plt.rcParams["font.sans-serif"] = [font]
break
plt.rcParams["axes.unicode_minus"] = False
set_chinese_font()
注意顺序:把字体设置放在任何画图代码之前,否则前面的图重新保存时依然会乱码。axes.unicode_minus是另一个高频坑,不设为False的话,坐标轴上的负号会被渲染成方块。
5.2 四张核心图表的绘制与解读
第一张是月度GMV趋势折线图,直观反映全年销售节奏。折线图是最适合展示时间趋势的图表,横轴是月份,纵轴是GMV。画完之后我叠加了一张6月和11月的标注,直接用plt.annotate在峰值点处添加两行注释文字,提醒观看者这两个时间点对应促销节点。
第二张是Top10商品横向条形图,我在Top商品分析中会点名各个支柱品类的表现情况。横向条形图通常比纵向更适合展示排名,因为商品名称文字较长,横向排布不会被底部坐标轴挤压。我先用sort_values排序再用barh绘制,从顶部到底部依次展示Top10。
第三张是类目占比饼图。饼图虽然经常被吐槽难以比较细微差异,但用来看大类的构成比例确实直观,三个大类的占比差异一眼就能看出。如果分类超过五个,我建议改用堆叠柱状图或者横向条形图,饼图在类别多时阅读效率反而很低。
第四张是用户购买频次分布直方图,横轴是用户的购买次数,纵轴是对应用户数量。为了让图更清晰,统计购买次数为2到10次以上的用户分布,然后用直方图展示。结果非常典型:购买1次的用户是绝对主体,二次购买开始急剧衰减,使用超过5次的用户几乎可以称得上忠实客户了。
每张图在画完后都要调用plt.tight_layout(),否则保存出来的图经常出现标题和标签互相遮挡的问题。下面是一个完整的趋势图画法示例:
python复制plt.figure(figsize=(12, 5))
monthly_gmv.plot(kind="line", marker="o", linewidth=2)
plt.title("2024年各月度GMV变化趋势")
plt.xlabel("月份")
plt.ylabel("GMV(元)")
plt.grid(alpha=0.3)
plt.tight_layout()
plt.savefig("monthly_gmv_trend.png", dpi=150)
plt.show()
保存图片用savefig而不是截图,dpi=150能保证放到PPT里不模糊。这一步虽然简单,但直接影响汇报效果。
5.3 图表结论要能对应到业务动作
可视化的终点不是把图画出来,而是让看图的人能直接做决策。我在交付图表时,每张图下面都会附一段“结论与建议”。月度趋势图对应的建议是“6月和11月的大促投入效果显著,可以把预算适度向前置预热期倾斜,拉长促销周期”;Top10商品图对应的建议是“针对头部单品建立库存预警机制,同时尝试在Top商品详情页做关联推荐,提升连带率”;复购率分布图对应的建议是“购买2到3次的用户是复购提升的黄金人群,可以集中发券召回”。
这样整套可视化才不是自嗨,而是真正帮业务方省下读数据的时间。你费劲做分析,最后一步沟通没做到位,前面全部白费。
6. 常见问题与排查技巧实录
6.1 高频报错速查表
整个项目跑下来,我遇到的报错和坑基本可以整理成一张表,给后面接手类似分析的人做参考:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 图表中文显示为方块 | 未设置中文字体 | 设置rcParams["font.sans-serif"],并确定系统里有对应字体 |
| 坐标轴负号显示为方块 | unicode_minus未关闭 |
设置plt.rcParams["axes.unicode_minus"] = False |
ModuleNotFoundError: No module named 'pandas' |
解释器选错,包没装到当前环境 | 在VSCode中重新选择虚拟环境解释器,或确认环境已激活 |
ValueError: cannot mask with array containing NA/NaN values |
判断条件里包含缺失值 | 先删除或填充NaN,再做布尔筛选 |
OutOfBoundsDatetime |
日期字符串格式异常 | 用to_datetime(..., errors="coerce"),然后检查NaT |
SettingWithCopyWarning |
对DataFrame切片后再赋值 | 用.copy()显式拷贝,避免链式赋值 |
| 订单量看起来比实际多很多 | 一单多商品行被重复计数 | 对order_id用nunique()去重 |
| 月度趋势图无法跨年区分 | 只提取了月数而没提取年份 | 用to_period("M")统一成“年-月” |
6.2 一个容易忽略的坑:不要轻易全局删除缺失值
新手最容易犯的错误是看到缺失值就想着dropna()全删,这样做风险很大。缺失只是一种表现形式,背后的原因才是关键。这次数据里total_amount缺失的17行,我经过排查发现它们的共有特征是都出现在凌晨两三点,且商品ID为空。我怀疑是支付回调接口在特定时段有偶发异常,这种情况如果只是简单删除,问题会在之后的数据管道里反复出现。
正确做法是把脏数据单独抽出来放一个bad_rows.csv,发回给数据提供方排查,同时把“为什么删、删了多少”写进分析说明。这才是让分析工作更专业化的细节,也是你和普通跑数工程师的区别。
6.3 性能优化:当数据量变大怎么办
17万行在pandas里算很小的数据,几乎所有操作都是秒级完成。但如果你以后遇到几百万行的订单数据,有几个习惯建议提前养成。
第一,只加载需要的列,用pd.read_csv("orders.csv", usecols=["order_id", "order_date", "total_amount"])能显著减少内存。第二,groupby之前先想想能不能把能合并的维度合并,减少聚合次数。第三,类型优化是杀手锏,比如把表示省份的字符串列转成category类型,把确实用不到浮点精度的金额字段转成float32,内存占用能降一半以上。第四,如果数据实在太大,可以考虑用polars或者DuckDB替代纯pandas,接口类似但性能强很多。
这次17万行数据我没有做以上优化,因为完全没必要。但代码结构上我已经把每一步都写成了函数,后续换更大数据时,函数内部可以平滑替换。
6.4 分析和汇报的边界感
最后说一个偏经验而非技术的问题。分析做完了,图表也画完了,但汇报时切忌只摆数字不给建议。运营人员真正需要的是“应该怎么办”的方向性判断。我在报告里就给运营提了三条可落地的建议:一是针对低频用户做定向召回,把复购率从22.7%往上推;二是围绕Top10爆款设计关联推荐,提升客单价;三是6月大促效果明显好于其他月份,建议把部分预算挪到预热期做“蓄水”。
通过这次项目我发现,真正拉开分析师差距的不是会不会写groupby,而是能不能把数据结论翻译成业务语言。这也是我给所有想往数据分析方向发展的朋友的核心建议:技术是工具,业务理解才是放大器。你写的每一行pandas代码,最终都要回答一个问题——然后呢?
