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

均值差 24 万不算证据,得把这个差放进波动里看——这就是 t 检验。 A 对 B 的 p 是 0.000071,A 对 C 的 p 是 0.55,一个显著一个不显著。 「没证据说不一样」不等于「证明一样」。这是统计里最容易说错的一句。

📝 本章和前面几章的关系

前面三篇都在描述数据。这一篇开始做推断:拿样本说话,判断两组是不是真有差别。 数据是三家门店十二个月的销售额,单位万元。三家的规模差不多,正好用来对比。

一、先看均值差,但别急着下结论

A 店月均 134.00 万,B 店 109.67 万,C 店 130.33 万。 A 比 B 高 24.33 万,A 比 C 只高 3.67 万。 直觉会说「A 比 B 强,A 和 C 差不多」。但直觉没算上波动。

A 店标准差 15.84,B 店只有 6.89,C 店 13.38。 B 店虽然低,但稳;A 店高,可波动大。这两个信息都得进模型。

二、t 检验:把差除以波动

t 值的算法很朴素:两组的均值差,除以「这个差的标准误」。 差得大、波动小,t 就大;差得小、波动大,t 就小。 算出来 A 对 B 是 t = 4.879,A 对 C 是 t = 0.613。

t 大不大,要换成 p 才好判断。p 是「如果两组真的一样,出现这么大差距的概率」。 A 对 B 的 p 是 0.000071,A 对 C 的 p 是 0.55。

三、p 小于 0.05 意味着什么

p 小,说明「两组一样」这个假设站不住,差异不太可能是巧合。 0.05 是个习惯门槛,不是自然定律。医学常用 0.05,物理实验要小得多。 别把 0.05 当开关。p 是 0.049 和 0.051,实际含义几乎一样,结论却翻了个面。

所以现在更提倡报具体的 p 值,而不是只说「显著 / 不显著」。

四、p 大不等于一样

A 对 C 的 p 是 0.55,只能说明「没有足够证据说它们不一样」。 样本只有十二个月,A 比 C 多卖 3.67 万,完全可能是巧合。 「没证据说不一样」和「证明一样」是两件事。

就像没找到钥匙,不等于钥匙不存在。样本不够时,结论只能停在「不知道」。

五、差异有多大:效应量

p 只回答「有没有」,不回答「有多大」。样本一大,一点点差也能显著。 所以还要算效应量。这次用 Cohen's d:均值差除以合并标准差。 A 对 B 的 d 是 1.99。一般 0.2 算小、0.5 算中、0.8 算大。

1.99 远大于 0.8,说明不只是「显著」,而且差得实打实。 一句完整的结论要带三个数:均值差、p 值、效应量。少一个都不够。

六、动手 Demo:差异化分析:两组人真不一样吗

三家门店的月度销售额,先看均值和标准差,再做 t 检验。 A 对 B 显著、A 对 C 不显著,正好一正一反,把这套方法的边界看全。

import numpy as np
from scipy import stats

SA = [118, 112, 125, 121, 132, 128, 141, 136, 130, 142, 155, 168]
SB = [105, 108, 98, 112, 101, 115, 108, 118, 104, 111, 120, 116]
SC = [126, 108, 119, 133, 124, 121, 138, 129, 125, 135, 148, 158]

for nm, a in (("A 店", SA), ("B 店", SB), ("C 店", SC)):
    print("%s 均值 %.2f,标准差 %.2f" % (nm, np.mean(a), np.std(a, ddof=1)))

t1, p1 = stats.ttest_ind(SA, SB)
t2, p2 = stats.ttest_ind(SA, SC)
print("A 对 B:t = %.3f,p = %.6f" % (t1, p1))
print("A 对 C:t = %.3f,p = %.4f" % (t2, p2))

pooled = np.sqrt((np.var(SA, ddof=1) + np.var(SB, ddof=1)) / 2)
print("Cohen's d = %.2f" % ((np.mean(SA) - np.mean(SB)) / pooled))

实跑输出:

--------------------------------------------------------------------
差异化分析:两组人真不一样吗
--------------------------------------------------------------------

  ① 先看均值差
  --------------------------------------------------------------------
  A 店:均值 134.00 万元,标准差 15.84,最小 112,最大 168。
  B 店:均值 109.67 万元,标准差 6.89,最小 98,最大 120。
  C 店:均值 130.33 万元,标准差 13.38,最小 108,最大 158。
  A 店比 B 店月均高 24.33 万元。
  A 店比 C 店月均只高 3.67 万元。
  ! 均值差不能直接下结论。差 24 万和差 3.7 万,得看这个差在波动里算不算大。

  ② t 检验:把差除以波动
  --------------------------------------------------------------------
  A 店对 B 店:t = 4.879,p = 0.000071。
  A 店对 C 店:t = 0.613,p = 0.5464。
  A 对 B 的 p 只有 0.000071,远小于 0.05;A 对 C 的 p 是 0.55,大于 0.05。
  ! t 值就是「差」除以「差的标准误」。差得大、波动小,t 就大,p 就小。

  ③ p 大不等于一样
  --------------------------------------------------------------------
  A 对 C 的 p 是 0.55,只能说明「没有足够证据说它们不一样」。
  样本只有十二个月,一年里 A 店比 C 店多卖 3.7 万,完全可能是巧合。
  「没证据说不一样」和「证明一样」是两件事。这是统计里最容易说错的一句话。
  ! 想要更强的话,样本得加长:三年、五年的月度数据,结论才站得住。

  ④ 差异有多大:效应量
  --------------------------------------------------------------------
  A 对 B 的 Cohen's d = 1.99。一般 0.2 算小、0.5 算中、0.8 算大。
  这次远大于 0.8,说明不只是「显著」,而且差得实打实。
  ! 只看 p 会被样本量骗。样本足够大时,1 块钱的差也能显著,所以还要报效应量。

ttest_ind 的 ind 是 independent,独立样本。同一批人前后各测一次要用 ttest_rel。 ddof=1 这里不能省:样本标准差除的是 n 减 1,和 numpy 默认的 ddof=0 不一样。 p 打出来是 0.000071,用 %.6f 才看得见。写成 %.2f 只会显示 0.00,看起来像「零概率」。

30 秒实验

  1. 把 C 店每个月都加 10 万,再跟 A 店比,看 p 会不会掉到 0.05 以下。
  2. 把 A 店的 12 个月只取前 6 个月,跟 B 店的前 6 个月比,看 p 变成多少。
  3. 想一想:如果 A 店只比 B 店高 1 万,但样本有十年,p 会不会显著?这说明什么?

常见误区

  1. 只看均值差不看波动:差 24 万在波动 16 万里算大,差 3.7 万就不一定。
  2. 把 p 大当成「证明一样」:只能说没有足够证据,不能说两者相同。
  3. 把 0.05 当开关:0.049 和 0.051 的实际差别可以忽略。
  4. 只报 p 不报效应量:样本够大时,微不足道的差也会显著。
自测三问(点开对答案) 1. t 值是什么除以什么? —— 两组的均值差,除以这个差的标准误。 2. A 对 C 的 p 是 0.55,该怎么表述? —— 「没有足够证据说明两家不一样」,不能说「证明两家一样」。 3. 为什么 p 小还要看效应量? —— p 只回答有没有差异,不回答差异多大。样本一大,小差也能显著。

两组比完了。下一篇换一种问法:两个变量是不是一起变,以及为什么这不等于因果。

相关笔记