📊 第4章 Pandas 进阶
📄 一句话概括

quantile(0.65) 的意思是「65% 的数据在这条线以下」。参数是比例,不是 65。 它是插值算出来的,不是「排第几就是第几」,所以会出现小数。 分位数是「按位置切」,均值是「按总量平摊」。分档、排名、去极值都用它。

📝 本章和前面几章的关系

前三篇算的都是「一个数概括全体」。这一篇算的是「一条线,把数据切成两半」。 第 3 章框异常值用的 IQR 就是两个分位数相减,这里把底细讲清楚。

一、一个分位:quantile(0.65)

语文 quantile(0.65) 等于 87.55。 意思是:65% 的数据在 87.55 以下,35% 在以上。 参数是比例不是百分数。写 65 会报错或给出离谱的结果,要写 0.65。

低于 87.55 的有 6 人——不是 6.5 人,因为数据点太稀,切不出正好 65%。 所以分位数的「65%」是个期望值,实际卡在哪个位置要看数据密度。

二、一次要多个分位

分位 语文
25% 76.00
50% 84.00
75% 89.50
90% 92.30

传一个列表进去,返回的还是一个 Series,索引就是分位。 50% 分位等于中位数 84.0——两个函数算出来一定一样,可以互相验算。 25%、50%、75% 这三个就是四分位,箱线图上那个盒子就是它们围出来的。

IQR 等于 Q3 减 Q1,这里就是 89.50 减 76.00 = 13.50。

三、分位数是怎么插出来的

语文排好序:68、72、75、79、83、85、88、90、92、95。一共 10 个数。 位置 = 0.65 × (10 - 1) = 5.85,落在第 6 个和第 7 个之间。 第 6 个是 85,第 7 个是 88,按 0.85 的比例插值:85 + 0.85 × 3 = 87.55。

和 quantile 给的一模一样。分位数是插出来的,不是「排第几就是第几」。 这就是它会出现 84.5、87.55 这种小数、而不是原始分数的原因。

四、分位数能干什么

用途 怎么写
切档 按 90% 分位划线,前 10% 是优秀
去极值(缩尾) 把 5% 以下和 95% 以上压回边界
框异常值 Q1-1.5IQR 到 Q3+1.5IQR 之外算异常
看分布形状 比较 Q1 到中位数、中位数到 Q3 的距离

切档最常用:绩效考核按 20/70/10 分三档,就是两个分位数两条线。 去极值不删数据,只是把超出边界的值拉回来,保住样本量的同时压住极端值。 分位数按位置切,均值按总量平摊。两者的用途从根上就不一样。

五、动手 Demo:分位数:一刀切掉 35%

先算 quantile(0.65),再手算一遍插值过程,最后要四个常用分位。 中间会数一下低于这条线的有几个人,体会「比例」和「人数」的差别。

import pandas as pd

S = pd.Series([88, 92, 75, 85, 90, 68, 95, 72, 83, 79])

Q65 = S.quantile(0.65)
print("quantile(0.65) = %.2f" % Q65)
print("低于这条线 %d 人" % (S < Q65).sum())

QS = S.quantile([0.25, 0.5, 0.75, 0.9])
print(QS.round(2).to_string())
print("50%% 分位 %.1f,中位数 %.1f" % (QS[0.5], S.median()))

V = sorted(S.tolist())
POS = 0.65 * (len(V) - 1)
LO, HI = int(POS), int(POS) + 1
print("排序 %s" % V)
print("位置 %.2f,在 %d 和 %d 之间" % (POS, V[LO], V[HI]))
print("插值 %.2f" % (V[LO] + (POS - LO) * (V[HI] - V[LO])))

实跑输出:

--------------------------------------------------------------------
分位数:一刀切掉 35%
--------------------------------------------------------------------

  ① 一个数:quantile(0.65)
  --------------------------------------------------------------------
  语文 quantile(0.65) = 87.55。
  意思是:65% 的人在这条线以下,35% 的人在这条线以上。
  低于这条线的有 6 人。
  ! quantile 的参数是「比例」不是「百分数」。写 65 会报错,要写 0.65。

  ② 一次要多个分位
  --------------------------------------------------------------------

| 分位 | 语文 |
|---|---:|
| 25% | 76.00 |
| 50% | 84.00 |
| 75% | 89.50 |
| 90% | 92.30 |

  传一个列表进去,返回的还是一个 Series,索引是分位。
  50% 分位就是中位数 84.0,两个函数算出来一定一样。
  ! 四分位就是 25%、50%、75% 这三个,箱线图上的盒子就是它们围出来的。

  ③ 分位数怎么插出来的
  --------------------------------------------------------------------
  语文排好序:68、72、75、79、83、85、88、90、92、95。
  0.65 的位置 = 0.65 × (10 - 1) = 5.85,落在第 6 个和第 7 个数之间。
  第 6 个是 85,第 7 个是 88,按 0.85 的比例插值:85 + 0.85 × (88 - 85) = 87.55。
  ! 分位数是插出来的,不是「排第几就是第几」。所以它会出现小数。

  ④ 分位数能干什么
  --------------------------------------------------------------------
  切档:把语文按 90% 分位切,前 10% 划成「优秀」。
  去极值:把两头 5% 和 95% 之外的数压回边界,叫缩尾。
  算 IQR:Q3 减 Q1,就是第 3 章框异常值用的那个宽度。
  ! 分位数是「按位置切」,均值是「按总量平摊」。分档、排名、去极值都用分位数。

最后两行是手算版:V[LO] + 比例 × (V[HI] - V[LO]),结果和 quantile 一分不差。 分位数会插值。所以「第 65 百分位是 87.55 分」这种话不能理解成「有人考了 87.55」。

30 秒实验

  1. 把 0.65 改成 65,看 pandas 报什么(或者给出什么离谱结果)。
  2. 算 quantile(0.5) 和 median(),确认两个数一模一样。
  3. 想一想:Q1=76.00、中位数=84.00、Q3=89.50,这三段距离说明分布往哪边偏?

常见误区

  1. quantile 里写 65:参数是比例,写 65 等于要 6500% 分位。
  2. 以为分位数一定是数据里出现过的值:它是插出来的,可能是谁都没考过的分。
  3. 把 65% 分位理解成「正好 65% 的人在下面」:数据点稀的时候切不准。
  4. 用均值和分位数混着讲分布:一个按总量,一个按位置,两套口径不能混。
自测三问(点开对答案) 1. quantile(0.9) 和「前 10%」是什么关系? —— 90% 的数据在这条线以下,剩下 10% 在这条线以上,所以它就是「前 10% 的门槛」。 2. 为什么分位数会出现小数? —— 它是按位置插值算出来的:位置 5.85 落在第 6、7 个数之间,按比例取中间值。 3. IQR 怎么算,用来干什么? —— IQR 等于 Q3 减 Q1。它框出中间一半数据的宽度,配 1.5 倍用来找异常值。

算完数还得让人看得懂。下一篇讲怎么把 0.0523 显示成 5.2%。

相关笔记