刚把店址固定住,又发现降价的三家社区店去年都换了店长。第二个混杂因素出现了。 再拆一层,每组剩不到一家——样本撑不住了。观察数据能拆的层数是有限的。 这一篇讲观察数据的三个死结,以及为什么最后只能走向实验。
上一篇拆开了店址,方向找回来了。这一篇要处理的是「拆完还不够」这件事。 「样本撑不住拆分」会在第 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 秒实验
- 如果门店有 80 家而不是 8 家,三层拆分还撑得住吗?
- 算一下:要在四格里每格至少 5 家,总共需要多少家店?
- 想一想:如果只能加一家店,你该加在哪个格子里?
常见误区
- 硬拆:拆到每格一家还照算,得到的差值全是噪声。
- 用「趋势明显」代替证据:这话在样本不够时最常出现,也最没用。
- 为了凑样本合并格子:把商圈和社区合并,等于把混杂因素又请回来了。
- 以为多做几轮问卷能救:问卷救不了分组不均,只有随机分组能。
自测三问(点开对答案)
1. 为什么「换店长」是混杂因素? —— 它同时影响降不降价(新官上任想做事)和销售额(管理变了),且不是降价造成的。 2. 拆到每格一家,问题出在哪? —— 没有格内变异可估计,任何差值都无法判断是效应还是噪声。 3. 观察数据回答不了因果,报告该怎么写? —— 写清「能排除什么、不能排除什么」,再建议做一次实验。硬答比不答更有害。既然观察数据走到头了,那就自己做一次。下一篇讲实验的两条腿:控制组和差值。
- ☐ (本篇完,下一篇 2.6 控制组与一个月之后)