鸣众数研← 科研教学
基础 / DID 从零入门 / B56

从零做 DID:手算、回归与独立迁移

政策实施后处理组的变化,为什么还要减去对照组的变化?

使用工具 Stata + Python 独立复核 · 先修 会读表格、求均值和做减法;运行 Stata 前可先学 Stata 入门

把这门课学到能独立操作

学习记录只保存在当前浏览器。完成状态由章节勾选、数值核对和作业自查共同组成,不是能力认证。

进入分层作业

01 / 观察与比较

先看这次练习得到什么

主例复用 Card 与 Krueger 1992 年两州快餐门店调查的既有四格汇总。反事实情景和另一份8家门店、2期的16行面板均为明确标注的教学设定。

2.75360578真实汇总DID
0.58802137处理组前后变化
3.0模拟迁移DID
两组趋势与反事实
案例处理组变化对照组变化DID
公开调查四格0.58802137-2.16558442.7536058
改变反事实趋势0.58802137-11.5880214
原创模拟门店523

真实调查按本课已有完整就业分项口径汇总,DID为2.75360578,保留与论文表3的2.76之差。四格回归残差自由度为0,不提供门店层面的标准误或平行趋势检验。情景和迁移数据均非新实证证据。

本课成果

交四格均值、两次差、交互项核对、新数据作业及一段识别边界说明。

02 / 跟着数据运行

从输入到成果

课堂练习.do

代码行号对应实操包中的完整脚本。请先运行完整脚本,再按步骤修改与比较。四格回归用于比较点估计。

03 / 讲义与作业

理解操作背后的判断

01 开始之前:文件、软件与一次完整运行

本课先用纸笔完成四个均值,再用软件核对。下载完整课堂包并全部解压,文件夹内应有两州就业汇总.csv、反事实情景.csv、独立练习_模拟门店.csv,以及课堂练习.do和课堂练习.py。不要直接在压缩包浏览窗口里双击脚本,也不要只复制一份代码到另一个空文件夹;程序需要在同一位置找到输入。

在自己的授权Stata中,先保存当前工作,再在命令窗口输入cd "实际解压目录"。Windows路径可以写D:/课程/DID;路径必须换成自己的。输入pwd确认当前位置,再用Do-file Editor打开课堂练习.do。先通读开头的clear、set more off和日志命令,确认清空的是本次可重新读取的内存数据,随后运行整份do文件。不要把终端命令python或Windows双击说明输入Stata命令窗口。

第一次运行按顺序观察四行数据、两组变化、交互项和模拟结果,并查看目录中新生成的Stata四格均值结果.csv、Stata模拟四格结果.csv及文本日志。尚无Stata时,可先按网站的本课Python环境准备入口运行Python独立复核,输出包括DID核对结果.csv和趋势图。在 Stata 中用同一份数据核对结果。每次练习都保留自己的代码与结果。

02 先确定谁被处理、谁作参照以及什么时候比较

DID的第一步是明确比较设计。主例中处理组是新泽西州调查门店,对照组是宾夕法尼亚州东部调查门店,政策前和政策后是两轮调查。背景是1992年4月新泽西最低工资提高;本课不重新开展调查,也不把这个案例自动推广到其他行业或年代。处理组身份必须依据制度事实确定,不能看哪一组结果上升就把哪一组叫处理组。

在纸上画一个两行两列的格子。行写处理组、对照组,列写政策前、政策后。每一格应对应同一结果概念、明确分母和相应时期。随包真实资料每行是地区与调查时期的汇总;独立作业每行则是一家模拟门店在一个时期的记录。这两个文件的行数不能当作相同层级的样本量。

主程序先assert合法州别和调查时期,再建立treat与post。表达式(州别 == "新泽西州")在条件成立时生成1,否则为0;因此先检查允许值非常重要,拼错州名不能默默被当成正确对照。post为1表示政策后,不表示是否属于处理组。isid treat post要求四种组合各只有一行,重复行或缺格应先回查输入。

03 读懂四格:为什么不能直接比较就业总量

两州门店数不同,各轮有效记录也可能不同。新泽西政策前的均值是6561.05除以321,约为20.43940810;政策后是6707.75除以319,约为21.02742947。宾州东部两格分别是1796.50除以77和1629.75除以77,约为23.33116883和21.16558442。用计算器逐格复算一次,再与CSV中总量和分母相对照。

这里的结果单位是每家门店的平均全职当量。它由全职员工、经理及副经理与兼职人数的一半构成,不等于“实际多雇了多少个人”。6561.05也不是门店均值,321更不是两轮合并后的独立门店数。直接把两州合计作差,会混入门店数量不同的影响。遇到单位变更,先统一结果定义,再考虑估计方法。

代码用generate double avgfte = 全职当量合计 / 有效门店数保存均值,用format调整显示位数。format不会把底层数据截断;手算时尽量保留足够精度,到展示时再四舍五入。先把四格都截成两位再相减,会得到与完整精度不同的数字。真实汇总按各轮就业分项完整记录整理,前后分母321和319不同,不应称为已经锁定同一批完整追踪门店。

04 第一次相减看变化,第二次相减扣除参照变化

始终沿同一方向计算“政策后减政策前”。新泽西的变化为21.02742947减20.43940810,约增加0.58802137;宾州东部的变化为21.16558442减23.33116883,约减少2.16558442。DID再计算处理组变化减对照组变化,即0.58802137减去负的2.16558442,得到约2.75360578。先在纸上保留括号,可以避免把减负数误写成加负数。

0.5880是处理组自身的前后差,2.7536是两组的变化差。两者回答的问题不同。若把0.5880直接解释成政策效应,就隐含无政策时处理组平均结果不会变化;DID改用参照组同期变化作为反事实变化的依据。这个依据是否可信需要制度和样本论证,计算公式本身不能证明。

Stata每执行一次summarize,r(mean)就更新为这一次的均值。脚本在每次计算后立即保存到不同scalar中:tb、ta、cb、ca分别是处理组前后和对照组前后。quietly只是不显示命令结果,不会跳过计算。如果只运行最后一行did表达式而没有运行前面的标量赋值,可能出现未定义或沿用旧内存值;重新从导入开始顺序运行最容易定位问题。

05 把看不见的反事实画出来

我们观察到了新泽西政策后的实际均值,却观察不到同一批门店在同一时期“没有这次调薪”时的结果。两期DID用处理组政策前均值加上对照组同期变化,构造反事实后期均值。本例约为20.43940810加负2.16558442,即18.27382368。实际后期21.02742947与它的距离仍是2.75360578。

趋势图中黑实线连处理组观察值,灰虚线连对照组观察值,点线表示平行趋势假设下的处理组反事实。点线不是额外采到的第三组数据。纵轴注明每店平均全职当量,并从16起绘制可读刻度;读图时应看刻度与数值,不能把线条角度或线间距离当成脱离坐标轴的证据。

平行趋势要求无政策时两组的平均变化相近,并不要求政策前水平相同。起点20.44和23.33不同本身不能否定DID;只看两条观察线在政策后分开也不能验证假设。当前只有一个政策前时点,没有前期趋势序列,不能用这四格做政策前趋势检验。补充更多政策前资料有助诊断,但“前期未显著不同”也不能证明不可观察的反事实一定成立。

06 用交互回归核对同一个点估计

模型包含四项:常数、处理组指示、后期指示、处理组与后期的乘积。把对照组政策前作为基准,常数对应对照组前期均值;处理组项对应前期组间差;后期项对应对照组变化;交互项就是两组的变化差。可以把四种0/1组合代入模型,按四格逐一检验每项承担的作用。

Stata命令regress avgfte ib0.treat##ib0.post显式把0设为基准。双井号会加入两个主项及交互项;只写一个井号或只手工加入treat乘post,可能漏掉用于区分初始组间差和共同时间变化的项。运行后读取_b[1.treat#1.post],与前面保存的did比较。脚本的assert要求二者差小于很小的数值容差,Python也用四行设计矩阵独立核对。

本课四个汇总观察拟合四个参数,残差自由度是0。回归表中的标准误、t值或区间缺失是这个饱和练习的结构,不是通过换一个vce选项就能补出的信息。不要复制四行很多遍制造样本量,也不要将有效门店数当频数权重就声称恢复了原始门店的不确定性。四格均值没有提供组内方差、前后协方差和抽样设计所需信息。

07 从算对数字到写对研究结论

可先写一条描述性结果:“按本课随包的四格汇总,新泽西门店的平均全职当量变化比宾州东部高约2.7536。”如果进一步写成政策影响,应说明平行趋势、无差异性同期冲击、无影响比较的溢出、无提前反应,以及样本构成和测量口径可比等条件。这些条件不能靠一个显著性标记代替。

本课已有汇总算得2.75360578,原论文表3报告2.76。两者保留各自口径,不能为了让数字完全相同改动原数据。2.75360578按两位小数通常显示2.75,因此差异不能简单说成这一数值四舍五入就等于2.76。当前包只交付既有完整分项口径的汇总,没有重做论文全部微观筛选、平衡样本和标准误程序。核对精度、分母和样本定义比抹平差异更重要。

样本范围是这次调查的连锁快餐门店和观察期。用“所有餐饮企业都多雇了2.75人”表述,会同时扩大适用总体、混淆全职当量与人数,并省去识别条件。作业中的文字说明需要人工判断;网页数值核对通过,只说明所填结果与指定练习相符,不能自动证明因果设计有效或论文结论成立。

08 改做:换一个明确标注的对照趋势

现在把计算中的反事实假设拿出来观察。打开反事实情景.csv,看到假设对照组变化为-1。它不是从真实调查估计出的新值。保持新泽西两格不变,假设宾州东部每店只减少1个全职当量,新的反事实后期就是20.43940810减1,新的DID就是0.58802137减负1,约为1.58802137。

先独立写出两个算式,再运行脚本的情景步骤。Stata使用preserve和restore暂存并恢复真实四格,情景表只有一行;读到的数值先存成scalar,再计算。Python单独读取情景文件,并把这一行结果明确标成课堂假设。检查真实两州CSV的分母和总量仍未改变,这是区分观察资料和反事实练习的基本习惯。

完成指定作业后,可以复制情景文件的备份,把假设变化改为0再运行,理解为什么此时DID等于处理组前后差。不要去改真实调查的宾州总量来假装这一情景发生过。网页指定作业仍按-1的原始情景核对,探索其他数值时应在自己的答案中记录改动参数、结果和假设性质,完成后恢复原情景以便复核。

09 独立做:换一份门店面板重建四格

独立练习_模拟门店.csv包含8家虚构门店、两期共16行。它由本课原创构造:试点组各店增加5,参照组各店增加2,意在检验你是否能从更细的记录重新计算,而不是提供一项真实政策证据。先复制迁移练习起步.do,按注释补命令,暂时不要打开迁移练习参考.do。

先用门店编号与时期检查联合唯一性,再确认每家门店有两期、组别不会在两期之间改变。这里每个格子都有4家门店,按组别和时期求简单平均即可。处理组均值从13变到18,对照组从11变到13。独立算出处理组变化5、对照组变化2和DID为3,再用交互回归核对。Stata参考脚本先collapse成四格,仍只作点估计演示。

如果得到2或5,分别检查是否只提交了对照变化或处理变化;如果得到-3,检查处理组编码和减法方向;如果记录数是8,检查是不是只统计了门店数而题目要求门店-时期记录数。本例没有缺失和进入退出。真实研究中这些问题可能改变观察组成,不能为凑成平衡面板就把未观察格填0,也不能默认删掉不齐全门店后仍估计同一个总体。

10 提交、复核与下一步学习

交付至少包含输入版本说明、可重跑的代码、四格结果表,以及说明单位、资料性质和识别边界的一段文字。真实主例与假设情景、模拟迁移分别命名,不能把它们叠在一张表里却省略性质。核对数值时保留足够精度,展示时可写四位小数。把代码中的路径设为实际解压目录,不把个人电脑的绝对路径当成别人也具备的环境。

按跟做、改做、独立做的次序完成三项作业。参考答案解释了为什么得到这些值;如果数字不同,先查分母和四格是否完整,再查处理组、后期及相减方向,最后检查是否提前取整。网页会核对数值并给出检查提示;能否说明反事实条件、是否混淆观察单位、代码能否从输入重跑,仍需按人工评分标准逐项检查。

完成后可以继续学习政策文件编码、更多前期的事件图,以及分批实施政策的比较组选择。两组两期的简洁公式不能直接替代多期研究设计。先把当前一个问题讲清楚:这次比较用谁作参照、凭什么作参照、估计量的单位是什么,以及有哪些问题这份资料还回答不了。保留出错日志与修复记录,会比只保留最后一张漂亮表更有助于下一次研究。

分层作业:跟做、改做、独立做

数值检查只覆盖本题指定口径。代码质量、解释与识别条件请逐项自查,不由网页自动判定。

跟做:从真实四格算出两次差

使用两州就业汇总.csv,先手算每格总量除以本格门店数,再填写处理组变化、对照组变化和DID;提交Stata或Python核对结果。

提交内容:一张保留分母的四格表、三个数值以及结果单位。

提示 1

所有变化都按政策后减政策前计算。

提示 2

DID是处理变化减对照变化,对照变化为负时注意括号。

按每个输入框标注的单位填写数值,不加单位文字;可以填写小数。

查看参考解释

处理组变化约0.58802137;对照组变化约-2.16558442;两次差约2.75360578。保留与论文2.76的口径差异。

改做:改变反事实中的共同趋势

读取反事实情景.csv中-1的指定假设,保持真实新泽西两格不变,计算新泽西反事实后期均值和新的DID。原调查CSV不得覆盖。

提交内容:一张带“课堂假设”标记的情景表和两个算式。

提示 1

反事实后期=处理组前期+假设的对照变化。

提示 2

DID也可以用处理组实际后期减新的反事实后期得到。

按每个输入框标注的单位填写数值,不加单位文字;可以填写小数。

查看参考解释

假设对照变化为-1,反事实后期约19.43940810,情景DID约1.58802137。它不能替换真实案例估计。

独立做:从新门店面板重建四格

独立使用独立练习_模拟门店.csv和迁移练习起步.do,检查主键及两期覆盖,重建四格,计算处理组变化和DID。先完成再打开参考脚本。

提交内容:已补全的起步代码、四格表及一段注明模拟性质的结果说明。

提示 1

先数门店-时期记录,再数独立门店,二者不同。

提示 2

每格都有4家门店,按组别、时期求均值。

提示 3

检查处理组前后差和对照组前后差,最后再相减。

按每个输入框标注的单位填写数值,不加单位文字;可以填写小数。

查看参考解释

16条记录、8家门店;处理组均值13到18,对照组11到13;处理变化5,对照变化2,DID=3。

遇到问题怎样定位

Stata提示文件找不到,常见r(601)

原因:工作目录没有指向完整解压文件夹,或只复制了do文件。

操作:先输入pwd查看目录,再用cd "实际路径"切换,确认CSV文件存在且文件名未被改为.csv.txt。

复查:重新运行导入步骤,count应是4。

四格主键检查报重复或不唯一

原因:追加了重复资料、州别或时期录入错误,或输入实际上是门店明细。

操作:用list核对州别与调查时期,确认当前读的是两州就业汇总.csv;不要直接duplicates drop掩盖冲突。

复查:合法组合只有处理前、处理后、对照前、对照后四行。

DID变成负的2.7536或只得到0.5880

原因:相减方向颠倒,或只算了处理组前后变化。

操作:把四格均值写成纸面算式,所有变化用后减前,再按处理变化减对照变化。

复查:对照变化为负,真实主例DID约正2.7536。

Stata回归标准误或t值缺失

原因:四格拟合四个参数,残差自由度为0。

操作:保留这个限制,读取点估计与e(df_r);需要微观推断时另备合适的原始记录与设计,不能复制行数凑样本。

复查:交互系数与手算相同,e(df_r)为0。

最后一行标量计算报错或得到上次结果

原因:跳着执行导致tb、ta等标量未创建,或旧会话状态残留。

操作:从文件开头顺序运行,确认每次summarize后立即保存r(mean)。

复查:四个标量分别对应本次四格均值。

图上两组起点不同,就以为平行趋势失败

原因:把相同水平与相同反事实变化混在一起。

操作:分别说明前期水平差与趋势假设;写下“当前只有一个前期,无法检验前期趋势”。

复查:解释围绕无政策时的平均变化,未把图形外观当成检验结果。

Python提示ModuleNotFoundError: numpy

原因:用到了不含本课固定依赖的其他Python解释器。

操作:按本课Python环境准备配置,然后使用课程运行入口;不要随意升级系统包或把不同环境的运行结果混用。

复查:本课独立复核生成三种情景的结果表。

改了反事实参数后网页答案不通过

原因:网页按指定的-1情景核对,而你正在探索其他参数。

操作:先保存探索记录,恢复原情景完成指定作业;其他参数的结果单独解释,不覆盖真实资料。

复查:原情景反事实约19.4394、DID约1.5880;探索表写清自己的参数。

返回三门样板课学习路线 →

补充练习与参考答案

1. 四格均值回归为什么不能提供门店层面标准误?

只有4个汇总观察却拟合4个参数,残差自由度为0;四格汇总也没有提供所需的门店方差与前后协方差。

2. 政策前两组水平不同,是否已经否定平行趋势?

没有。平行趋势针对无政策时的平均变化。只有一个前期,当前四格无法检验政策前趋势。

3. 把2.75360578写成“与论文2.76仅有四舍五入差别”是否恰当?

不恰当,该数按两位小数是2.75。应保留差异,回查样本、分母和精度;当前有限汇总不等于论文完整微观复现。

课堂自测 你只保留了四个地区-时期均值,却看到Stata标准误缺失,下一步应怎样做?


阅读材料

04 / 带到自己的电脑

下载与运行

本课软件与五步学习

主软件:Stata。请先完成本软件的首次运行,再进入本课;其他软件不要求安装Python。

请先下载本页完整实操包并全部解压,保留所有文件;下方单文件仅供查阅,启动入口须在完整包内运行。

打开Stata五步准备指南 → · 下载本课操作说明 · 原生入口:课堂练习.do · 原生入口:迁移练习参考.do · 原生入口:迁移练习起步.do
可选:Python独立复核

本课主软件为Stata。以下仅用于独立核对,不要求先安装Python才能学习原生操作。

查看Python分步笔记本(在完整包内学习) · 查看Windows准备入口源码(在包内运行) · 查看Windows打开入口源码(在包内运行)

Mac 可使用包内的 .command 启动文件。

  1. 选择本课软件路线

    本课主路线为Stata。软件准备指南:/learning-setup#stata。只准备本路线需要的工具。

  2. 完成一次学习准备

    先检查已有软件。Python主课或选做Python独立复核时,首次/修复使用prepare-python.cmd(Windows)或prepare-python.command(Mac);日常打开使用open-python对应入口。其他软件按各自指南准备,不先装Python。

  3. 第一次跑通并保存

    打开Stata,按本软件指南进入示例项目。打开示例数据,运行一次分析或操作,看到结果,保存文件并找到它。仅安装成功还不能算跑通。

  4. 打开本课项目

    完整解压课程包。打开课堂练习.do、迁移练习参考.do、迁移练习起步.do。课程输入和作业分别保存;兼容课程复用已准备环境,不在每节课重复安装。

  5. 按步骤学习并改做

    按本课分步实操运行,逐项核对预期结果。再复制课程目录,修改参数或换用独立作业数据;保留基准版本,不覆盖原始资料。

本课需要的软件

  • 商业软件需使用自己的有效授权;课程材料不含许可证。

四格回归用于比较点估计。

逐项下载与成果文件

同组学习

← 返回完整课程目录