Python渠道分析实战:从指标口径到自动化PPT
2026/9/17 13:59:42 网站建设 项目流程

简介:康师傅方便面渠道分析PPT,是一份面向市场营销、渠道管理及快消品行业学习者的案例分析型资源,适合用于课程展示、论文参考或企业内部分享。内容系统梳理了康师傅方便面从1992年至今的渠道演进历程,涵盖“国营制”“大经销商制”“通路精耕制”和“精准式行销”四个阶段,并详细拆解一阶、二阶、三阶渠道以及农贸批发市场自然辐射模式;同时针对终端市场控制力不足、价格体系混乱、窜货现象严重等现实问题,给出了经销商选择评估与窜货整治等对策。资源打包为1个PPT文件,大小约638KB,页面结构清晰,图表结合便于理解。已有93人学习,对把握快消品渠道设计、渠道冲突治理与精细化分销策略具有实用参考价值。

1. 康师傅方便面渠道分析:先搞清楚问题,再去做PPT

某次月度经营分析会上,销售总监打开一份全是累计销售额表格的PPT,董事长问了一句:"现代渠道这个月掉量,到底是门店数量少了,还是货架被竞品挤压了?"会议室安静了十几秒。做快消品渠道分析的朋友应该都有同感:报表没少做,但问题没被回答。康师傅方便面这类产品,渠道结构非常典型——现代渠道里有NKA大卖场、CVS便利店,传统渠道里有批发和食杂店,电商渠道还有平台电商和O2O即时零售。渠道分析如果只停留在"汇总销售额、画张饼图",很难定位掉量原因。这篇文章不做理论本,直接讲落地路径:先定指标口径,再清洗多源数据,最后用Python把图表和结论自动生成PPT。

2. 渠道分析先立指标:铺货率、动销率、货架份额怎么算

做渠道分析最忌讳直接打开流水表开干。不同部门对"铺货率"的理解可以差出十几个百分点,原因通常只是分母不同。所以我会在分析文件里先放一张"指标口径表",固定下来再写代码。否则后面算出来的数字,销售不认,市场部也不认。

2.1 先分清楚渠道层级:现代、传统、电商

康师傅方便面的渠道通常分三层:L1是大盘(现代、传统、电商),L2是每个大盘下的细分,L3一般到具体客户。PPT里最多分析到L2,再细分会淹没在噪声里。常见划分如下。

渠道L1渠道L2典型客户/场景
现代NKA沃尔玛、大润发
现代LKA区域连锁超市
现代CVS全家、7-11
传统批发批发市场档口
传统食杂店夫妻老婆店
电商B2C天猫旗舰店、京东自营
电商O2O美团闪购、京东到家

这是很普遍的划分,实际以企业内部主数据为准。做分析时,渠道字段至少要保证到L2。如果一个经销商既供批发又供食杂店,就需要在门店主数据里单独打标,不能混用。

2.2 五个核心指标口径

指标看什么计算口径
数值铺货率覆盖广度有该SKU记录的门店数 / 该渠道总门店数
加权铺货率覆盖质量有该SKU门店的品类销售额 / 该渠道全部门店品类销售额
动销率卖不卖得动期间内有销售记录的门店数 / 有铺货记录的门店数
缺货率断供情况结转缺货门店数 / 应陈列门店数
货架份额陈列竞争本品货架面数 / 同类商品货架面数(电商不适用)

加权铺货率的重点是给大店更大的权重。比如在A渠道铺了1000家小店,在B渠道铺了300家大卖场,数值铺货率A渠道更高,但加权铺货率B渠道可能反超。方便面高度依赖冲动购买,货架位置直接影响动销,所以货架份额这个指标不能省。

2.3 用Pandas算指标

下面这段代码按销售流水和门店主数据,算数值铺货率、加权铺货率和动销率。

import pandas as pd # 字段:store_id 门店, product_id SKU, qty 销量, is_listed 是否有铺货标记 df = pd.read_csv('sales_detail.csv', parse_dates=['date']) store = pd.read_csv('store_master.csv') # 字段:store_id, channel_l2, cat_sales df = df.merge(store, on='store_id', how='left') # 数值铺货率:按渠道和SKU,有铺货记录的门店数 / 该渠道总门店数 listed = df[df['is_listed'] == 1].groupby( ['channel_l2', 'product_id'])['store_id'].nunique().rename('listed_stores') total = store.groupby('channel_l2')['store_id'].nunique().rename('total_stores') coverage = listed.to_frame().join(total, on='channel_l2') coverage['数值铺货率'] = coverage['listed_stores'] / coverage['total_stores'] # 加权铺货率:有铺货门店的品类销售额 / 该渠道全部门店品类销售额 w_listed = df[df['is_listed'] == 1].groupby( ['channel_l2', 'product_id'])['cat_sales'].sum().rename('w_listed') w_total = store.groupby('channel_l2')['cat_sales'].sum().rename('w_total') weighted = w_listed.to_frame().join(w_total, on='channel_l2') weighted['加权铺货率'] = weighted['w_listed'] / weighted['w_total'] # 动销率:有销售记录的门店数 / 有铺货记录的门店数 sell_stores = df[df['qty'] > 0].groupby( ['channel_l2', 'product_id'])['store_id'].nunique().rename('sell_stores') sellout = sell_stores.to_frame().join(listed, how='left') sellout['动销率'] = sellout['sell_stores'] / sellout['listed_stores'] print(coverage.head()) print(weighted.head()) print(sellout.head())

代码逻辑说明:

  • mergehow='left'保留流水全部行,避免丢订单;如果门店主数据没匹配上,cat_sales会是空值,需要在分析前回填或标记。
  • nunique()是按门店ID去重,不是按记录数,这是铺货率的关键。如果重复统计,铺货率会虚高。
  • 动销率的分母是有铺货记录的门店,而不是全部门店。这样衡量的是"铺上以后卖不卖得动",与铺货率互不干扰。
  • 想看全品汇总时,把product_id去掉即可,但建议先按单品看再看聚合,避免单品波动被平均掩盖。

提示:is_listed必须来自初中上架记录或进销存里的铺货单,不能用销售大于0反推,否则铺货率永远等于动销率,指标就失去意义了。

3. 渠道数据清洗:把ERP流水和经销商报表做成渠道维度表

零售数据不会按分析维度摆好等你。ERP里的客户类型、经销商管报里的区域、电商后台的店铺名,字段千奇百怪。清洗的目标是形成一张统一的渠道维度表,后续指标代码全部依赖这张表。

3.1 建立渠道映射表,而不是在代码里写replace

常见做法是维护一个CSV映射文件,新增渠道时只改配置,不动代码。下面是一个最小的映射表示例。

raw_channel,channel_l1,channel_l2 大润发,现代,NKA 沃尔玛,现代,NKA 华润万家,现代,NKA 全家,现代,CVS 7TT,现代,CVS 批发市场,传统,批发 食杂店,传统,食杂店 天猫旗舰店,电商,B2C 京东自营,电商,B2C 美团闪购,电商,O2O

merge做映射,而不是replace

import pandas as pd map_df = pd.read_csv('channel_map.csv') raw = pd.read_csv('sales_detail_raw.csv') raw = raw.merge(map_df, on='raw_channel', how='left') # 查看未匹配的渠道 unmatched = raw[raw['channel_l1'].isna()] print(unmatched['raw_channel'].value_counts(normalize=True)) # 未匹配的统一归为“其他”,但要记录占比 raw['channel_l1'] = raw['channel_l1'].fillna('其他') raw['channel_l2'] = raw['channel_l2'].fillna('其他')

参数说明:

  • mergehow='left'保留左表全部行。如果某渠道名没有映射,对应渠道维度是空值,用value_counts(normalize=True)看占比。超过1%的渠道必须回填映射,说明这个客户很重要,不能当脏数据丢掉。
  • 不建议用df.replace做一对多映射,因为渠道名可能有空格、大小写、前后缀,replace的模式会越写越长,后期无法维护。

3.2 区分出货口径与动销口径,避免重复统计

方便面的渠道数据至少有两个来源:经销商进销存和门店POS。如果混在一起,同一个商品可能先算出货,再算动销,销售额叠了两遍。分析PPT首页必须先写明本页用的是哪个口径。

重复检查代码:

# 同一门店、同一SKU、同一日期、同一批次只应有一条记录 dup_check = df.groupby(['store_id', 'product_id', 'date', 'batch_no']).size() dups = dup_check[dup_check > 1] print(f'重复记录数: {len(dups)}') # 如果批次字段缺失,用下单时间近似判断 df['order_hour'] = df['date'].dt.floor('H') dup_check2 = df.groupby(['store_id', 'product_id', 'order_hour']).size() print(dup_check2[dup_check2 > 1].head())

逻辑说明:第一段是精确查重,要求有批次号;第二段是降级方案,以小时粒度近似,只看重复规模,不作为删数据依据。

3.3 时间口径统一:春节档和同比的错位

方便面有非常强的节日脉冲,春节档前后销量占比很高。自然月同比很容易失真:去年1月是春节前,今年1月是春节后,两个月份不可比。常见做法是维护一张春节档日期表,把每个自然日映射到对应的销售档期。

festival = pd.DataFrame({ 'date': pd.date_range('2024-01-01', '2024-12-31'), 'festival': ['春节前'] * 40 + ['春节档'] * 20 + ['节后'] * 305 }) # 实际应按农历日期生成映射,这里示意 df = df.merge(festival, on='date', how='left')

说明:示例中硬编码了区间,实际操作要按农历生成。我的做法是先汇总三年农历腊月十六到正月十五的日期区间,做成一个字典再映射,不要在分析代码里写死。

3.4 同店增长计算

现代渠道开新店会抬升销售额,传统渠道门店倒闭会让总量下降。如果不剔除开店关店,渠道增长率的解释力很弱。同店增长只比较存量门店。

cur = df[(df['date'] >= '2024-01-01') & (df['date'] <= '2024-01-31')] pre = df[(df['date'] >= '2023-01-01') & (df['date'] <= '2023-01-31')] common = set(cur['store_id']) & set(pre['store_id']) same_store = cur[cur['store_id'].isin(common)].groupby('channel_l2')['amount'].sum() same_store_pre = pre[pre['store_id'].isin(common)].groupby('channel_l2')['amount'].sum() sss_growth = (same_store / same_store_pre - 1).rename('同店增长率') print(sss_growth)

注意:这里先取交集门店,再分别汇总。门店编码在第二年可能变化,需要借助门店主数据里的开业日期判断,不能用简单的字符串匹配。

4. 用Python生成渠道分析PPT:从matplotlib图表到pptx文件

每周或者每月重复做渠道PPT,最烦的不是分析,而是粘贴图表。Python可以一次跑完分析和输出,保证每周的图表、配色、坐标轴规范一致。

4.1 图表选择与业务场景匹配

分析目标图表类型为什么
渠道销售结构变化100%堆叠柱状图看清占比移动
渠道同比增速对比柱线组合图柱看规模,线看增速
区域×渠道矩阵气泡图三维信息在一页
单渠道单月趋势带去年同期的折线图判断季节性

4.2 先用matplotlib画图,再插入PPT

import pandas as pd import matplotlib.pyplot as plt from pptx import Presentation from pptx.util import Inches import tempfile # 示例汇总数据:渠道销售额与增长率 summary = pd.DataFrame({ 'channel': ['现代', '传统', '电商'], 'amount': [1250, 980, 730], 'growth': [3, -5, 12] }) fig, ax = plt.subplots(figsize=(10, 4)) ax.bar(summary['channel'], summary['amount'], color=['#d71920', '#f4a81d', '#2c6e9c']) ax.set_title('各渠道销售额(万元)') ax.set_ylabel('销售额(万元)') for i, v in enumerate(summary['amount']): ax.text(i, v + 10, f'{v:.0f}', ha='center') ax.axhline(0, color='grey', linewidth=0.8) plt.tight_layout() # 保存为临时图片,后续插入PPT with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as f: fig.savefig(f.name, dpi=200) img_path = f.name plt.close() # 创建PPT prs = Presentation() slide = prs.slides.add_slide(prs.slide_layouts[6]) slide.shapes.add_textbox( Inches(0.6), Inches(0.3), Inches(8), Inches(0.6) ).text_frame.text = '渠道销售额对比' slide.shapes.add_picture(img_path, Inches(0.6), Inches(1.0), width=Inches(8.5)) prs.save('channel_analysis.pptx')

要点说明:

  • add_textbox返回的 shape 可以继续往text_frame里加段落,先写标题后加图,保证不重叠。
  • add_picture只指定width,高度会按比例自动计算,避免拉伸变形。如果图片本身比例不协调,优先在 matplotlib 里用figsize控制长宽比。
  • 图片保存成临时文件再插入,不要用BytesIO。python-pptx 对BytesIO的支持不太稳定,本地路径最稳。

4.3 使用python-pptx原生图表,方便后续改数据

有些场合需要保留可编辑的图表,可以在PPT里直接加原生chart。

from pptx.chart.data import CategoryChartData from pptx.enum.chart import XL_CHART_TYPE chart_data = CategoryChartData() chart_data.categories = summary['channel'] chart_data.add_series('销售额(万元)', tuple(summary['amount'])) slide = prs.slides.add_slide(prs.slide_layouts[6]) graphic_frame = slide.shapes.add_chart( XL_CHART_TYPE.COLUMN_CLUSTERED, Inches(0.6), Inches(1.2), Inches(8.0), Inches(4.5), chart_data )

参数说明:

  • XL_CHART_TYPE.COLUMN_CLUSTERED是簇状柱形图,换成折线图用XL_CHART_TYPE.LINE_MARKERS,饼图用PIE
  • 位置参数依次是left, top, width, height,单位都是Inches()。16:9页面宽度约10英寸,留出页边距后图表宽度不要超过9英寸。

4.4 图表字体和颜色规范

参数建议值原因
dpi200投影不虚
中文字体微软雅黑或Noto Sans CJK避免PPT显示方框
主色不超过3种渠道对比用色相近会分不清
图表标题带结论,如"现代渠道销售额下降5%"引导阅读顺序

中文字体设置代码:

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'Noto Sans CJK SC'] plt.rcParams['axes.unicode_minus'] = False

如果不设置,matplotlib会显示警告,图里中文变成框。axes.unicode_minus关闭减号渲染,避免负号变方框。

5. 康师傅方便面渠道分析PPT的最后一公里:用结论倒排页面

数据和图表都有了,PPT最后拼的是叙事。渠道分析PPT最容易犯的毛病是把所有图表按时间顺序堆上去,汇报十分钟还没讲到重点。我一般会先写结论,再倒排页面结构。

先用一句话回答三个问题:这个月哪些渠道掉量,掉量的主因是覆盖问题还是动销问题;需要渠道经理下周做什么动作。然后把结论写成标题栏。比如"现代渠道掉量5%,主因NKA缺货率上升"比"现代渠道销售分析"有用得多。

图表注释不要写"销售额变化趋势",要写"红线为平均线,12月跌到线下且未修复"。在matplotlib里可以用annotate标出异常点:

ax.annotate( '缺货率上升12个百分点', xy=(2, 12), xytext=(1.2, 20), arrowprops=dict(arrowstyle='->', color='black') )

补充一个快消品渠道分析经常被忽视的细节:渠道经理在会议上真正关心的是"我还有多少货架要被竞品抢走"。所以在PPT的最后,放一个"下月动作清单",把铺货率、动销率、缺货率三个指标直接对应到责任人和动作,而不是只放分析结论。

自检技巧:每页PPT只放一张主图,标题是结论,图里标注异常点。如果有人提问"电商铺货率多少",把第一页的快照表翻出来就能答上。快照表列:渠道、数值铺货率、加权铺货率、动销率、缺货率、同比增减。这样整个PPT就可以从"数据报告"变成"决策工具"。最后再走一遍数据逻辑:任何结论都要能在图里找到依据,找不到就删掉那一页。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询