📈 第2章 实验
📄 一句话概括

刚把店址固定住,又发现降价的三家社区店去年都换了店长。第二个混杂因素出现了。 再拆一层,每组剩不到一家——样本撑不住了。观察数据能拆的层数是有限的。 这一篇讲观察数据的三个死结,以及为什么最后只能走向实验。

📝 本章和前面几章的关系

上一篇拆开了店址,方向找回来了。这一篇要处理的是「拆完还不够」这件事。 「样本撑不住拆分」会在第 11 章变成正式的方法:分割数据、分区模型。那里是主动分,这里是被迫分。

一、第二个混杂因素

降价的三家社区店,去年都换了店长。新店长上任,排班、出品、服务全变了。 店长能力同时影响「降不降价」(新官上任三把火)和「卖得好不好」。三条腿又齐了。 于是上一轮的结论又开始晃:那 3 个百分点里,有多少是降价,有多少是新店长?

二、再拆一层,样本就没了

八家店按店址切成四格,每格一到三家。再按「换没换店长」切,每格零到两家。

层数 格子数 每格平均家数 能不能下结论
不拆 2 4 能,但有偏
按店址 4 2 勉强
再加店长 8 1 不能

每格一家店,那个「格内差异」就是这一家店自己,没有方差可言。

三、观察数据的三个死结

分组不是你分的:你只能看着已经发生的事,没法决定谁进哪组。 混杂只能想到才拆:想不到的变量永远看不见,而且它不会报错。 越拆越空:每拆一层样本就少一半,拆到后面误差比效应还大。

三个死结叠在一起,结论就是:这类问题观察数据回答不了。

四、承认回答不了,是一种能力

很多报告错就错在硬答。数据撑不住,就用「趋势明显」「基本可以判断」这类话糊过去。 诚实的写法是:现有数据能排除 A,不能排除 B 和 C,要定因果必须做实验。 这句话不会让报告显得弱,反而让后面那句「我建议做一次实验」变得有分量。

五、从观察走向实验

实验做的事很简单:分组由你决定。 一旦分组由你决定,混杂因素就被随机化打散了——它不再系统性地偏向某一组。 代价是要花钱、要等时间、要说服业务方配合。但这是唯一能说因果的路。

六、动手 Demo:情况更糟:观察数据救不回来了

同一份数据,拆一层、拆两层,看每格还剩几家。 这段代码不产生新结论,它只做一件事:把「样本不够」这件事算给你看。

from collections import Counter

stores = [('S01', 'community', True, 120.0), ('S02', 'community', True, 110.0),
          ('S03', 'community', True, 90.0), ('S04', 'downtown', True, 80.0),
          ('S05', 'downtown', False, 130.0), ('S06', 'downtown', False, 100.0),
          ('S07', 'downtown', False, 85.0), ('S08', 'community', False, 75.0)]
# 降价的三家社区店去年都换了店长
newmgr = {'S01': True, 'S02': True, 'S03': True}

def count(keyf):
    c = Counter()
    for s in stores:
        c[keyf(s)] += 1
    return c

cases = [('不拆', lambda s: 'all'),
         ('按店址+降价', lambda s: (s[1], s[2])),
         ('再加店长', lambda s: (s[1], s[2], newmgr.get(s[0], False)))]
for label, keyf in cases:
    c = count(keyf)
    print('%-12s %d 格  每格 %s  最小 %d'
          % (label, len(c), sorted(c.values()), min(c.values())))

实跑输出:

--------------------------------------------------------------------
情况更糟:观察数据救不回来了
--------------------------------------------------------------------

  ① 又发现一个混杂因素
  --------------------------------------------------------------------
  降价的三家社区店,恰好都在去年换了店长。
  新店长上任,排班、出品、服务全变了——这也是个能同时影响两边的变量。
  再拆一层?社区店降价组只剩三家,拆完每组一家,样本没了。

  ② 数据量撑不住拆分
  --------------------------------------------------------------------

| 店址 | 降价 | 现在几组 | 再按店长拆完 |
|---|---|---:|---:|
| 社区 | 降 | 3 | 3 |
| 社区 | 没降 | 1 | 1 |
| 商圈 | 降 | 1 | 1 |
| 商圈 | 没降 | 3 | 3 |

  八家店已经切成四格,每格一到三家;再切一刀,每格零到两家。
  ! 观察数据能拆的层数是有限的,因为层数一多,每层就空了。

  ③ 观察数据的三个死结
  --------------------------------------------------------------------
  第一,你只能看到「已经发生的分组」,没法决定谁进哪组。
  第二,混杂因素你只能想到才拆得动,想不到就永远看不见。
  第三,拆到后面样本不够,结论的误差比效应本身还大。

  ④ 于是只剩一条路
  --------------------------------------------------------------------
  自己决定谁降价、谁不降价。
  这一步一迈出去,你就从「观察」进入了「实验」——数据从「捡来的」变成「造出来的」。
  造出来的数据有一个捡来的数据永远比不上的好处:你知道分组是怎么分的。

三行分别是 2 格(各 4 家)、4 格(各 2 家)、8 格(各 1 家)。 每格一家的时候,「格内平均」就等于这一家本身,统计上已经没法估计波动。

30 秒实验

  1. 如果门店有 80 家而不是 8 家,三层拆分还撑得住吗?
  2. 算一下:要在四格里每格至少 5 家,总共需要多少家店?
  3. 想一想:如果只能加一家店,你该加在哪个格子里?

常见误区

  1. 硬拆:拆到每格一家还照算,得到的差值全是噪声。
  2. 用「趋势明显」代替证据:这话在样本不够时最常出现,也最没用。
  3. 为了凑样本合并格子:把商圈和社区合并,等于把混杂因素又请回来了。
  4. 以为多做几轮问卷能救:问卷救不了分组不均,只有随机分组能。
自测三问(点开对答案) 1. 为什么「换店长」是混杂因素? —— 它同时影响降不降价(新官上任想做事)和销售额(管理变了),且不是降价造成的。 2. 拆到每格一家,问题出在哪? —— 没有格内变异可估计,任何差值都无法判断是效应还是噪声。 3. 观察数据回答不了因果,报告该怎么写? —— 写清「能排除什么、不能排除什么」,再建议做一次实验。硬答比不答更有害。

既然观察数据走到头了,那就自己做一次。下一篇讲实验的两条腿:控制组和差值。

相关笔记