📊 第7章 数据统计分析案例
📄 一句话概括

对比分析就三步:先排序,再定分母,最后算占比。顺序错了结论就散。 平均值不等于中间水平。十五个品类里只有六个在平均线以上。 名次只是顺序,差距才是信息。第 1 和第 2 差 24 万,第 9 和第 10 只差 11 万。

📝 本章和前面几章的关系

从这一章起不再讲单个函数,讲一整套分析怎么做。第一篇是最基础的对比分析。 数据是自造的:一家连锁书店十五个品类的 2025 年销售额,单位万元。比例关系是真的,数字是编的。

一、先看整体:平均值会骗人

十五个品类,全年合计 1586 万元,平均每个品类 105.73 万元。 但只有 6 个品类在平均线以上,9 个在下面。 这就是平均值的老毛病:少数大数把线拉高,多数品类看着都「不及格」。

最高文学 252 万,最低体育 22 万,一头一尾差 6.1 倍。 报平均必须先看分布。分布偏得厉害时,中位数比平均值更像个「中间水平」。

二、排序:对比的前提

十五个品类按销售额从高到低排,前十名是文学、少儿、教辅、科技、生活、 艺术、经管、外语、计算机、考试。 第一名文学 252 万,第十名考试 57 万,前十名加起来 1415 万。

不排序就没法对比。「文学卖得好」这句话,只有在「比谁好、好多少」之后才成立。 Pandas 里就一句 sort_values,排完记得 reset_index,否则下标还留着原来的顺序。

三、三种比法,三个数

比法 分母 冠军的数
跟总量比 全年合计 1586 万 15.89%
跟最高比 冠军自己 252 万 100%
跟平均比 品类均值 105.73 万 2.38 倍

第二名是冠军的 90.5%,第三名是 81.3%,前三名合起来占全盘的 43.19%。 同一个「第一」,三种比法给三个完全不同的数。 所以报占比必须说清分母:占全盘、占冠军、还是占平均。不说清,读者只能猜。

四、名次之间的差距才是信息

相邻两名一减,差距最大的是第 5 名和第 6 名,差了 32 万元。 差距最小的是第 9 名和第 10 名,只差 11 万元。 同样是「相邻两名」,一个差 32 万,一个差 11 万。

第 5 名和第 6 名之间是一道坎,说明这两个品类不在一个量级上。 第 9 和第 10 几乎并肩,谁上谁下都可能,这种名次不值得当结论。

五、前十之外还有多少

前十名 1415 万,剩下 5 个品类只有 171 万,占一成多。 这 171 万里最小的体育只有 22 万,还不到文学的十分之一。 TOP10 是个习惯,不是一条天然的分界线。

真要决策,得问「砍掉后五名能省多少成本、少多少收入」,光看排名不够。

六、动手 Demo:对比分析:TOP10 怎么排

用 Pandas 把十五个品类排一遍,算占比、比平均、看相邻名次的差距。 数据全部写死在代码里,不依赖外部文件,直接能跑。

import pandas as pd

CAT = ["文学", "少儿", "教辅", "科技", "生活", "艺术", "经管",
       "外语", "计算机", "考试", "医学", "法律", "农业", "体育", "其他"]
VAL = [252, 228, 205, 175, 145, 113, 92, 80, 68, 57, 44, 36, 28, 22, 41]

df = pd.DataFrame({"品类": CAT, "销售额": VAL})
total = df["销售额"].sum()
print("合计 %d 万元,平均 %.2f 万元" % (total, df["销售额"].mean()))
print("高于平均的品类:%d 个" % (df["销售额"] > df["销售额"].mean()).sum())

df = df.sort_values("销售额", ascending=False).reset_index(drop=True)
df.index = df.index + 1
df["占比"] = (df["销售额"] / total * 100).round(2)
print(df.head(10).to_string())

print("冠军占 %.2f%%,前三占 %.2f%%,前十占 %.2f%%"
      % (df["占比"].iloc[0], df["占比"].iloc[:3].sum(),
         df["占比"].iloc[:10].sum()))
print("冠军是平均的 %.2f 倍" % (df["销售额"].iloc[0] / (total / 15)))
print("前十合计 %d 万元,其余 %d 万元"
      % (df["销售额"].iloc[:10].sum(), df["销售额"].iloc[10:].sum()))

实跑输出:

--------------------------------------------------------------------
对比分析:TOP10 怎么排
--------------------------------------------------------------------

  ① 先把表摆出来
  --------------------------------------------------------------------
  十五个品类,2025 全年销售额合计 1586 万元。
  最高 文学 252 万元,最低 其他 41 万元,两者差 6.1 倍。
  十五个品类的平均是 105.73 万元——但多数品类都在平均线以下。
  只有 6 个品类在平均线以上,9 个在下面。
  ! 平均值不等于中间水平。十五个数里 6 个高于均值、9 个低于均值,这很正常。

  ② 排序:对比的前提
  --------------------------------------------------------------------
  按销售额从高到低排,前十名是:

| 名次 | 品类 | 销售额(万元) |
|---|---|---:|
| 1 | 文学 | 252 |
| 2 | 少儿 | 228 |
| 3 | 教辅 | 205 |
| 4 | 科技 | 175 |
| 5 | 生活 | 145 |
| 6 | 艺术 | 113 |
| 7 | 经管 | 92 |
| 8 | 外语 | 80 |
| 9 | 计算机 | 68 |
| 10 | 考试 | 57 |

  排名一变,后面的占比、累计占比才有意义。先排序是整套对比分析的起点。

  ③ 三个对比角度
  --------------------------------------------------------------------
  跟总量比:第一名占全盘的 15.89%,前三名占 43.19%,前十名占 89.22%。
  跟最高比:第二名是冠军的 90.5%,第三名是 81.3%。
  跟平均比:冠军是平均值的 2.38 倍。
  ! 同一个第一,三种比法给三个数。报「占比」必须说清跟谁比、分母是什么。

  ④ 前十名里最该注意的是谁
  --------------------------------------------------------------------
  相邻两名之间,差距最大的是第 5 名和第 6 名,差了 32 万元。
  差距最小的是第 9 名和第 10 名,只差 11 万元。
  前 10 名加起来是 1415 万元,剩下的 5 个品类只有 171 万元。
  ! 名次只是顺序,差距才是信息。第 1 和第 2 差 24 万,第 9 和第 10 只差 11 万。

df.index = df.index + 1 是把名次从 0 起改成 1 起。 排完序一定要 reset_index,否则下标还是原顺序。 to_string() 是为了在终端里对齐打印。交给 Notebook 或表格软件时不用它。 占比那一列是算出来的,不是手打的。任何一个数改了,占比跟着变,这才是表该有的样子。

30 秒实验

  1. 把「其他」并入「文学」,再排一次,看前十名和占比有什么变化。
  2. 把占比改成「占冠军的百分比」,看榜首是不是变成 100%。
  3. 想一想:如果要砍掉后五个品类,只看销售额够不够?还缺什么信息?

常见误区

  1. 拿平均值当中间水平:十五个数里九个在均值以下,这很正常。
  2. 不排序就直接比:十五个数字横着看,谁也看不出谁高谁低。
  3. 报占比不说分母:占全盘 15.89% 和占冠军 100% 是两件事。
  4. 把排名当结论:第 9 和第 10 只差 11 万,这种名次不该拿去做决定。
自测三问(点开对答案) 1. 为什么说平均值会骗人? —— 少数大数会把均值拉高。这次只有 6 个品类在均值以上,9 个在下面,多数都被「平均」。 2. 对比分析的三个标准步骤? —— 排序、定分母、算占比。排序在前,因为没有顺序就没有「比谁」。 3. 第 5 名和第 6 名差 32 万,这个数有什么用? —— 说明这里是一道坎,两个品类不在一个量级上,策略该分开定。

横向比完了,纵向怎么比?下一篇:同比、定比、环比,三个词三种分母。

相关笔记