简介:这份教案面向大数据技术类相关专业师生,聚焦新零售智能销售数据的可视化实战,帮助读者打通从数据获取、清洗规约到交互式图形绘制与工程分析报告撰写的完整链路。资源包内含1个PDF文件,约120KB,内容为第7章教案文档,涵盖教学目标、材料清单、引导性与探究性问题设计、重点难点梳理及理论实验教学过程,可直接用于备课或自学参考。目前已有3537人学习下载,热度较高。读者可从中获得新零售智能销售设备市场背景与项目分析流程的讲解,掌握使用Python读取CSV、JSON等格式数据及清洗异常值、缺失值的方法,学会借助pyecharts绘制销售趋势图、库存占比饼图与用户画像分析图,并了解如何系统组织分析思路、呈现分析结果、提炼业务洞察并撰写有说服力的工程分析报告,适合希望提升数据素养与可视化实战能力的学习者。
1. 新零售销售数据可视化:一份能直接照着讲的教案长什么样
带大数据方向实训课的老师大概都有过这种体验:教材上的案例数据太干净,学生照着敲完代码跑出图,下课就忘,真扔给他一份带缺失值、字段名乱七八糟的销售流水,立刻卡在pd.read_csv那一步。这份《Python数据可视化实战》第 7 章教案,选的是一个更接近真实场景的题目——某公司在广东省投放的新零售智能销售设备流水,从读数据、洗数据、规约数据一路做到 pyecharts 交互图,最后落到一份工程分析报告。它解决的不是"怎么画一张折线图",而是"一条完整的分析链路怎么走通"。适合两类人:一是要备这 8 学时课的讲师,二是想拿一个端到端案例练手的自学者。整章按 8 学时设计,理论 28 学时体系里占一章,实验环节拆成 8 个具体任务,颗粒度足够细。
2. 数据读取与清洗:从原始流水到能画图的 DataFrame
2.1 先搞清楚这份数据长什么样
教案里没有给出完整字段清单,但按新零售智能销售设备的典型埋点结构,一份销售流水通常包含:设备编号、商品大类(生鲜/一般商品)、商品名称、销售时间、销售金额、促销标记、会员/顾客 ID。常见做法是先读进来用info()和head()摸一遍底,别急着写清洗逻辑。这一步的意义在于,你得先知道哪些列是数值、哪些是字符串、哪些时间字段是脏的,后面规约才有依据。
import pandas as pd import numpy as np # 读原始销售流水,注意编码,新零售系统导出的 CSV 常见 gbk df = pd.read_csv("sales_raw.csv", encoding="gbk") # 先看结构,别急着清洗 print(df.info()) print(df.head()) print(df.isnull().sum()) # 每列缺失值数量 print(df["商品大类"].value_counts()) # 大类分布,确认有没有脏分类encoding参数是第一个坑,很多设备导出的中文 CSV 默认 gbk,用 utf-8 读会直接抛UnicodeDecodeError。isnull().sum()给出每列缺失规模,是决定"删还是填"的依据。value_counts()用来发现"生鲜"和"生鲜类"这种同义不同写的脏分类,这类问题不处理,后面按大类聚合会凭空多出几类。
2.2 清洗:缺失值、异常值、重复记录三件事
教案把清洗列为重点,实验环节也单列了"数据的预处理与规约"。清洗不是无脑dropna(),得按字段性质分开处理。销售金额缺失的记录通常直接删,因为金额是核心指标,填了反而误导;商品大类缺失可以按商品名称反查补全;时间字段缺失的记录要单独看,可能是设备时钟异常。
# 1. 删除销售金额缺失的行——核心指标不能瞎填 df = df.dropna(subset=["销售金额"]) # 2. 商品大类缺失,用商品名称映射补全 category_map = {"苹果": "生鲜", "白菜": "生鲜", "纸巾": "一般商品"} df["商品大类"] = df["商品大类"].fillna(df["商品名称"].map(category_map)) # 3. 异常值:销售金额为负或超过合理上限的,按业务规则剔除 df = df[(df["销售金额"] > 0) & (df["销售金额"] < 10000)] # 4. 去重:同一设备同一时间同一商品的重复上报 df = df.drop_duplicates(subset=["设备编号", "销售时间", "商品名称"]) # 5. 时间字段统一转 datetime,方便后面按月聚合 df["销售时间"] = pd.to_datetime(df["销售时间"], errors="coerce") df = df.dropna(subset=["销售时间"])每一步都有业务含义:金额为负可能是退货记录混进来了,超过 10000 的单笔销售在智能零售设备场景下大概率是异常上报。errors="coerce"让无法解析的时间变成 NaT 而不是直接报错,再统一删掉,比逐条 try-except 干净。去重的 subset 选三个字段,是因为同一笔交易可能被设备重复上报,但不同商品在同一时刻成交是正常的。
2.3 规约:把明细流水压成能分析的粒度
规约的目的教案里写得很清楚——把大量复杂数据简化成易分析的形式。原始流水是"每笔交易一行",但你要画的是"每天各大类销售金额""每月大类占比""促销与非促销周环比",这些都需要先聚合。规约不是丢数据,是换粒度。
# 按天 + 大类聚合销售金额,供折线图和饼图使用 daily = df.groupby([df["销售时间"].dt.date, "商品大类"])["销售金额"].sum().reset_index() daily.columns = ["日期", "商品大类", "销售金额"] # 按月 + 大类聚合,供占比饼图 df["月份"] = df["销售时间"].dt.to_period("M") monthly = df.groupby(["月份", "商品大类"])["销售金额"].sum().reset_index() # 促销标记规约成布尔,供周环比柱状图 df["是否促销"] = df["促销标记"].map({"是": True, "否": False, "1": True, "0": False})dt.date和dt.to_period("M")是 pandas 时间序列的两个常用粒度,前者出日期对象,后者出 Period,画图时 x 轴显示更规整。促销标记的映射要覆盖多种写法,真实系统里"是/否""1/0""Y/N"都可能出现,这一步不做,后面分组会漏掉一半数据。
3. pyecharts 交互图:销售、库存、用户三类图怎么落地
3.1 为什么选 pyecharts 而不是 matplotlib
教案明确用 pyecharts 画交互式图形,这个选型有道理。matplotlib 出的是静态图,适合写进报告;pyecharts 出的是 HTML,鼠标悬停能看具体数值,缩放能看细节,课堂上演示效果直接拉满。新零售这种带时间维度和多分类的数据,交互性带来的体验差距很明显。安装就一句pip install pyecharts,注意版本,1.x 和 0.5.x 的 API 完全不兼容,教案配套 PPT 如果是老版本,代码得跟着调。
pip install pyecharts # 如果要导出图片,还需要 snapshot-selenium 或 snapshot-phantomjs pip install snapshot-selenium3.2 销售分析图:折线图看趋势,饼图看结构
实验环节要求画"生鲜类商品和一般商品每天销售金额的折线图"和"按月各大类销售金额占比饼图"。折线图用Line,饼图用Pie,两个图的数据源就是上一章规约出来的daily和monthly。
from pyecharts.charts import Line, Pie from pyecharts import options as opts # 折线图:生鲜 vs 一般商品每日销售金额 line = Line() line.add_xaxis(sorted(daily["日期"].unique().tolist())) for cat in ["生鲜", "一般商品"]: sub = daily[daily["商品大类"] == cat].sort_values("日期") line.add_yaxis(cat, sub["销售金额"].tolist(), is_smooth=True) line.set_global_opts( title_opts=opts.TitleOpts(title="每日销售金额趋势"), xaxis_opts=opts.AxisOpts(name="日期"), yaxis_opts=opts.AxisOpts(name="销售金额(元)"), tooltip_opts=opts.TooltipOpts(trigger="axis"), # 悬停显示同一天两条线数值 ) line.render("sales_trend.html")is_smooth=True让折线平滑,趋势更直观,但要注意平滑会轻微扭曲真实波动,做严谨分析时建议关掉。trigger="axis"是折线图的关键配置,鼠标移到某一天能同时看到两个大类的数值,对比才有意义。饼图那边按月聚合,Pie的add方法传(类别, 数值)元组列表即可,radius参数可以做成环形图,视觉上更现代。
3.3 库存与用户分析图:柱状图和画像
实验要求画"促销商品和非促销商品销售金额的周环比增长率柱状图",以及"累计消费前 10 顾客画像"。周环比增长率要先按周聚合,再算(本周-上周)/上周,用Bar画。顾客画像这块,教案说的是"根据消费情况画像",常见做法是聚合出每个顾客的累计消费、购买频次、偏好大类,取前 10 名用柱状图或雷达图展示。
from pyecharts.charts import Bar # 周环比增长率 df["周"] = df["销售时间"].dt.isocalendar().week weekly = df.groupby(["周", "是否促销"])["销售金额"].sum().unstack() weekly["促销环比"] = weekly[True].pct_change() * 100 weekly["非促销环比"] = weekly[False].pct_change() * 100 bar = Bar() bar.add_xaxis(weekly.index.astype(str).tolist()) bar.add_yaxis("促销商品周环比(%)", weekly["促销环比"].round(2).tolist()) bar.add_yaxis("非促销商品周环比(%)", weekly["非促销环比"].round(2).tolist()) bar.set_global_opts(title_opts=opts.TitleOpts(title="周环比增长率对比")) bar.render("weekly_growth.html")pct_change()直接算环比,乘 100 转百分比,round(2)保留两位避免图上标签太长。unstack()把促销/非促销从行索引转成列,方便同时取两组数据。顾客画像的聚合逻辑类似,groupby("顾客ID").agg({"销售金额": "sum", "销售时间": "count"})拿到累计消费和频次,再nlargest(10, "销售金额")取前十。
4. 避坑与排查:这份教案落地时最容易翻车的五个点
4.1 中文乱码:图上是方块,CSV 读进来报错
现象:pyecharts 渲染出的 HTML 标题和坐标轴中文显示成方块,或者读 CSV 直接抛UnicodeDecodeError。原因:一是 CSV 编码不是 utf-8,二是 HTML 模板没声明字符集。解决:读文件时显式指定encoding="gbk"或encoding="utf-8-sig",pyecharts 生成的 HTML 默认带<meta charset="utf-8">,如果还乱码,检查是不是用文本编辑器另存时改了编码。
4.2 时间字段解析失败,聚合结果为空
现象:pd.to_datetime之后大量 NaT,按天聚合出来只有零星几天。原因:原始时间格式不统一,有的带秒有的不带,有的用斜杠有的用横杠。解决:先用errors="coerce"兜底,再抽样看几种格式,必要时用format参数指定,或者分多次to_datetime处理不同格式的子集。
4.3 pyecharts 版本不兼容,add_yaxis报参数错误
现象:照着老教程写line.add_yaxis("销量", data, mark_point=["max"]),运行报TypeError。原因:0.5.x 和 1.x 的 API 差异很大,mark_point在 1.x 里挪到了set_series_opts。解决:pip show pyecharts确认版本,1.x 统一用opts.MarkPointOpts配置,别混用两套写法。
4.4 周环比算出 inf 或 NaN
现象:柱状图上出现空白柱或无穷大。原因:上一周销售额为 0 时,pct_change会得到 inf;第一周没有上一周,结果是 NaN。解决:算之前把 0 替换成 NaN 或用fillna(0)处理,画图前dropna()掉第一周,或者用replace([np.inf, -np.inf], np.nan)清洗。
4.5 顾客画像取前 10 结果不对
现象:nlargest(10, "销售金额")取出来的顾客消费额差不多,看不出差异。原因:顾客 ID 字段有缺失或格式不一致,导致同一顾客被拆成多个 ID。解决:聚合前先dropna(subset=["顾客ID"]),再统一 ID 格式(去空格、转字符串),确认唯一顾客数合理后再取前十。
5. 从图到报告:分析思路怎么组织,结论怎么落
5.1 分析报告的四段式结构
教案把"撰写工程分析报告"列为核心能力,实验环节也要求最后产出报告。一份合格的分析报告不是图的堆砌,常见做法是按"数据来源与处理 → 分析结果 → 业务洞察 → 建议"四段走。数据来源部分交代清楚设备覆盖范围、时间跨度、清洗掉了多少记录,这是可信度的基础。分析结果部分按销售、库存、用户三条线展开,每条线先给图再给一句话结论。业务洞察要落到具体发现,比如"生鲜类周末销售明显高于工作日""促销商品的周环比波动比非促销大"。建议部分对应洞察给可执行动作,别写"加强管理"这种空话。
5.2 用一张汇总表把关键指标钉死
报告里最容易被追问的是"你这个结论基于什么数"。建议在报告开头放一张关键指标汇总表,把总销售额、日均销售额、生鲜占比、促销占比、Top10 顾客消费集中度列清楚。这样后面任何一张图、任何一个结论,都能回溯到具体数字。
| 指标 | 数值 | 说明 |
|---|---|---|
| 总销售额 | 按实际数据填 | 清洗后全量求和 |
| 日均销售额 | 总销售额/天数 | 剔除无销售日期 |
| 生鲜类占比 | 生鲜销售额/总销售额 | 反映品类结构 |
| 促销商品占比 | 促销销售额/总销售额 | 评估促销依赖度 |
| Top10 顾客集中度 | Top10 消费/总消费 | 判断用户集中风险 |
5.3 一个具体技巧:把 pyecharts 图嵌进报告
纯 HTML 报告可以直接用Page把多张图拼成一个页面,Page(layout=Page.DraggablePageLayout)支持拖拽布局,导出后就是一个可交互的分析看板。如果要写 Word 或 PDF 报告,用snapshot-selenium把图导成 PNG 再插入,注意导出前先render一次确保 HTML 正常。
from pyecharts.charts import Page page = Page(layout=Page.DraggablePageLayout) page.add(line, pie, bar) page.render("report_dashboard.html")DraggablePageLayout让每张图可以拖动调整位置,适合做课堂演示或交付给业务方看的看板。导出 PNG 时如果中文乱码,是 selenium 用的浏览器字体问题,换成本地已装中文字体的 Chrome 驱动即可。
我第一次带这个案例时,图全画完了才发现顾客 ID 字段有 30% 缺失,前十画像根本不可信,只能回头补数据校验。从那以后我每次做聚合分析前都强制先跑一遍isnull().sum()和nunique(),确认字段可用再往下走。希望这份拆解帮到你,把第 7 章这 8 学时真正落地成学生能带走的一条分析链路。
本文还有配套的精品资源,点击获取