前置条件与学习依赖 / PREREQUISITES
① 姊妹页(必读)
先读 12 显著性诊断实务:功效、效应量、共线性、影响点、函数形式、测量误差、遗漏变量、异质性、多重检验十大根因。本页是它的"操作手法地图",两页互为补充。
② 方法前置
已掌握 基准回归稳健性检验DID内生性;理解 reghdfe、聚类标准误、固定效应吸收逻辑。
③ 软件前置
Stata 17+,外部命令:winsor2reghdfeesttabrangestatfirthlogitrelogitpscore
④ 本页立场
不教调 p 值,只教判别与防线 红线条目原样收录仅为"识别与防御",切勿用于正式研究

00 为什么需要这个手法库:合法设定探索 vs p-hacking

在几乎任何一篇实证论文里,从"原始数据"到"正文那张星号表"之间,都存在大量可以自由选择的旋钮:样本切到哪一年、是否剔除那段特殊时期、用 1% 还是 5% 缩尾、先取对数还是先缩尾、加不加这个控制变量、用 OLS 还是 Poisson、把标准误聚在个体还是行业、核心解释变量用当期还是滞后一期……每一个旋钮单独看都"情有可原",可它们叠加起来,就能让一个原本 p=0.34 的结果,在试遍组合后恰好出现一个 p=0.04 的规格。Simmons, Nelson & Simonsohn (2011) 用仿真证明:只要在"是否加第二个因变量、是否补样本、用哪种控制"等少数几个自由度上自由选择,标称 5% 的假阳性率就可以膨胀到 60% 以上。Gelman & Loken (2013) 把这称为 garden of forking paths(花园分叉路径)——你甚至未必存心作恶,却每一步都"觉得合理"。

因此,实证研究的核心素养不在于"知道哪些旋钮能拧",而在于能区分两种性质完全不同的拧法

合法的设定探索 / 稳健性:旋钮在看到结果之前就由理论、制度惯例、数据结构或诊断预先决定;无论拧完后显著与否,你都会把这一档如实写进正文或附录。
p-hacking / 数据挖掘:旋钮是在看到结果之后决定的——试到某一档恰好 p<0.05,就把它写进正文,其余删稿。判别问句只有一句:"如果这个改动放在结果本来就显著的情况下,我还会做吗?"答否,即操纵。

本页把这些旋钮按操作层面分成五大类,逐一讲透:① 是什么操作;② 为什么它能改变显著性(机制);③ 可运行的 Stata 代码(全部用 set seed 的模拟数据);④ 合法性判别;⑤ 审稿人如何识破;⑥ 诚实替代做法。请把它当作一张"自我审计清单":当你下次想拧某个旋钮时,先查这张清单,确认它站在花园的哪一边。

⚠ 贯穿全页的三条规范警示(务必逐条记住)

① 加权(weight)必须有理论或抽样设计支撑——不能因为加权后显著才加;② 任何事后剔除样本,都必须"找到合理理由"并在分析前确定,而不是试出来;③ 滞后阶数、移动平均窗口、阶段划分的选择,合理性要注意——必须有经济理论或制度时点支撑,不能逐期扫到显著为止。这三句会在下文反复出现。

01 总览表:35 种手法一览(含红线条目)

下表是全页的导航地图。"何时合法"与"何时是红线"两列是判别核心;标记 红线 的条目几乎没有合法用途。G、H 两类是 2026 年补入的"因果识别诊断 + 透明度工具"专项——它们不是用来"调显著"的旋钮,而是用来证明你识别可信的必要诊断。

类别手法改变了什么何时合法何时是红线
A 样本数据A1 样本筛选/子样本N 与所识别的总体事前由制度/理论限定窗口(如政策期、剔除 ST)事后反复试年份/子样本直到显著
A2 样本量与功效SE ∝ 1/√N扩样本提升功效是合法设计改进超大样本下经济意义极小却靠 N 刷显著
A3 缺失值处理N 从 68138→75000删高缺失无信息变量,并报告口径变化删缺失变量只为"碰巧显著"
A4 极端值 winsor/trim尾部杠杆点事前固定分位(1/99),多档并列从 1/2/5% 里挑显著那档
A5 先 log 还是先 winsor顺序不同结果不同事先固定数据 pipeline 并说明换顺序试到显著
A6 影响诊断 Cook/DFBETA识别有杠杆点有明确错误记录才删按系数大小删观测(→ F1 红线)
B 变量测量B1 控制变量组合遗漏偏误/坏控制/共线/样本随缺失变理论驱动,Model1–3 逐级报告按 p 值逐个加控制直到过线
B2 核心变量定义操作化=重新识别事前理论定义,多定义稳健性遍历十几种定义挑显著的
B3 变量变换改善分布 vs 改变构念log 改善分布合法连续变量硬切分类制造显著
B4 量级/单位/倒数符号与尺度逆向指标正向化事前定义为翻符号或调单位反复试
B5 企业年龄控制缓解偏态ln(1+age) 常规做法
C 模型估计C1 换估计模型估计量与 SE按数据类型与理论选模型Ologit/Poisson/negbin 试到显著
C2 固定效应组合吸收不同维度不可观测按经济结构设定逐个加 FE 到"恰好显著"
C3 行业代码粒度i.Ind1/2/3稳健性报告各粒度挑恰好显著的粒度
C4 函数形式线性/U型/门槛/调节理论+RESET 支持的非线性试各种多项式到显著
C5 高维 FE 的 R²xtreg vs reghdfereghdfe 高效、R² 分项报告隐瞒 FE 导致的样本变化
C6 稀有事件因变量relogit/Firth诊断后采用小样本二值变量硬用普通 logit
D 统计推断D1 标准误/聚类t=β/SE,P 可从 .02 变 .20依数据真实相关结构选择挑最窄 SE 显著(红线边缘)
D2 加权 weights估计目标总体有理论或抽样设计支撑不能因为加权后显著才加
E 时间识别E1 时间结构/LagX_t→Y_t vs X_{t-1}→Y_t事前理论滞后结构L1/L2/L3 逐期扫到显著
E2 平行趋势不通过DID 识别威胁合并处理时点/事件研究诊断不通过却硬说通过
E3 逐步回归选控制数据挖掘按显著性逐步加入控制=红线
G DID 因果识别诊断G1 事件研究图 leads/lagspre期系数是否贴0全期报告、95%置信带只画post期"显得平行"
G2 pre-trend 联合检验 + pretrends(Roth)多期leads联合F报告p值;正视功效低"不显著=平行趋势成立"
G3 安慰剂检验 placebo伪处理时点/伪处理组随机化500-1000次画分布只挑安慰剂不显著那版
G4 动态效应/post期趋势post期系数轨迹事前报告动态假设只摘显著的post期讲故事
G5 csdid/did_imputation 下pre-trend交叠DID的诊断新估计量+事件期诊断交叠DID只跑TWFE不做诊断
G6 不通过时诊断与合法处理识别失败的补救局部窗口/合成DID/Bacon/如实报告事后改窗口/合并分组"凑通过"
H 透明度与多重检验H1 机制/中介与坏控制bad control偏误事前理论机制、DAG指导把撞变量/对撞因子当控制加
H2 异质性:事前分组 vs 事后挑子样本子样本=新假设事前理论+交互项检验跑完再挑显著的子样本讲故事
H3 多重检验校正 Bonferroni/FDR/BH多检验假阳性膨胀报告校正后p或FDR跑20个检验只挑显著的报
H4 specification curve全规格集合报告Simonsohn et al. 2020全曲线只从spec curve里截一段显著的
H5 样本量/功效报告 power功效不足→假不显著事前power分析+事后post-hoc不报告功效就喊"无效应"
H6 等价检验 TOSTCI与"无效应"的判定先设等价界值再做TOST把"不显著"当"无效应"
F 红线F1 留一系数排序删样本按结果反选样本几乎无合法用途最典型的数据操纵(见 danger 专节)

02 A 类 · 样本与数据操作(6 种)

A1样本筛选:换年份 / 剔除特殊时期 / 子样本

是什么:if 限定估计样本,例如 if Year>=2011if SOE==1、剔除 2008 金融危机或 2015 股灾。为什么能改显著性:样本期变了,X 与 Y 的共变结构、处理强度、噪声水平全变;子样本(国企/民企、东中西部)更直接地重新定义了"你在回答谁的因果问题"。合法性判别:如果窗口是由制度时点(政策实施年份、会计准则变更)或研究问题本身(只关心 2011 年政策之后)事前决定的,合法;如果是跑完全样本不显著,回头把 2015–2018 剔除、把国企单拎出来,那就是事后挑子样本,是红线。审稿人如何识破:正文样本区间与数据附录对不上、稳健性表里全样本与子样本方向相反却只报告显著那张、删改理由与正文叙事巧合。诚实替代:主回归报全样本;子样本、剔除危机年放进稳健性并全部报告;删样本的理由在论文设计阶段就写死。

stata · A1_样本筛选.do
* A1 样本筛选:合法(事前制度窗口) vs 红线(事后挑子样本)
clear all
set seed 101
set obs 1000
gen id = _n
gen year = 2005 + mod(_n,15)          // 2005-2019
gen soe = runiform()>0.5              // 国企虚拟
gen x  = rnormal()
gen y  = 0.2*x + rnormal(0,1.2)       // 真实效应偏弱

* (合法)事前由政策时点限定:2011年起
reg y x if year>=2011
* (合法)事前理论关心国企子样本,并报告交互项组间差异
reg y x if soe==1
gen x_soe = x*soe
reg y x soe x_soe
test x_soe                            // 必须用交互项验组间差异

* (红线演示,勿用于正式研究) 事后从2005..2019逐年试窗口
* forvalues s=2005/2019 {
*   quietly reg y x if year>=`s'
*   display "起始年=`s'  系数=" %6.3f _b[x] "  p=" %6.3f (2*ttail(e(df_r),abs(_b[x]/_se[x])))
* }
* 上面这段"扫窗口"在论文里只能作为敏感性曲线(specification curve)整体报告,
* 绝不能只挑其中一个显著的窗口写进正文。

A2样本量与功效:SE ∝ 1/√N 的双刃剑

是什么:OLS 标准误近似与 √N 成反比,N 翻四倍,SE 减半。机制:大样本下哪怕效应只有 0.02,也能被 t=β/SE 算出显著;小样本下真效应 0.4 也可能因功效不足而不显著。合法性判别:为提升功效而合规地扩样本、合并不平衡面板,合法;但反过来,靠堆 N 把一个经济意义可忽略的系数"刷"成三星,却不报告效应量与经济显著性,属于误导。审稿人如何识破:N 动辄十万、系数小到小数点后三位、论文却不换算成"占被解释变量均值百分之几"。诚实替代:每个星号旁配标准化效应与"X 加 1 个 SD 对 Y 的实际影响",区分统计显著与经济显著(详见姊妹页根因 2)。

stata · A2_样本量功效.do
* A2 样本量:同一小效应,N=200 不显著,N=20000 显著
clear all
set seed 202
forvalues n=200(4950)10000 {
    preserve
    quietly set obs `n'
    gen x = rnormal()
    gen y = 0.03*x + rnormal(0,1)     // 真实斜率极小(0.03)
    quietly reg y x
    display "N=" %6.0f `n' "  b=" %6.4f _b[x] "  t=" %6.2f (_b[x]/_se[x])
    restore
}
* 观察:N 越大 t 越大,但效应量始终是0.03
* 结论:大样本下的"显著"必须配经济显著性换算,否则是误导

A3缺失值处理:complete-case / 插补 / 删高缺失变量

是什么:常见做法有三种——完整观测回归(Stata 默认,自动丢掉任一变量缺失的行)、多重插补、以及直接删掉那个缺失率很高的变量机制:删掉一个高缺失控制变量后,原来被它拖累的那几千个观测"复活",样本量从 68138 涨到 75000,核心变量的系数和 SE 随之改变。合法性判别:一个变量缺失率 90%、几乎不含信息,删掉它并在文中说明口径变化,合法;但如果删它纯粹是因为"删完之后核心变量碰巧显著",且你不报告删前删后的样本量与系数对比,就是操纵。审稿人如何识破:描述性统计表 N 与回归表 N 对不上、稳健性附录里不同模型 N 忽大忽小又无解释。诚实替代:每个变量报告缺失率;删变量前后两套结果并列;必要时用 mi impute 多重插补做敏感性。

stata · A3_缺失值.do
* A3 删高缺失控制变量导致 N 变化
clear all
set seed 303
set obs 8000
gen x = rnormal()
gen y = 0.3*x + rnormal()
gen ctrl_missing = .
replace ctrl_missing = rnormal() in 1/7500      // 仅前7500个有值,500个缺失
gen ctrl_other = rnormal()

* 含高缺失变量:N 只剩 7500
reg y x ctrl_missing ctrl_other
* 删掉高缺失变量:N 回到 8000,样本变大、SE 变小
reg y x ctrl_other
* 诚实做法:报告两套 N,并说明删除理由
* 不诚实做法:发现删完后 x 变显著,就悄悄把 ctrl_missing 从表里删掉

A4极端值处理:winsorize(压回)vs trim(删除)

是什么:winsor2 var, cuts(1 99) 把首尾 1% 的观测压到 1%/99% 分位数(保留观测数);trim 则直接删掉首尾分位。还可按年份/行业分组缩尾:by(Year)by(Ind)机制:OLS 最小化平方误差,极端值拥有不成比例的杠杆;压回或删除会改变斜率与 SE,连控制变量的极端值也会把核心系数的 SE 撑大合法性判别:缩尾分位(1%/2%/5%)必须在分析前按惯例或数据分布预定,并多档并列报告;从几档里挑显著那档写正文、其余删稿,是 Simmons et al. (2011) 证明的假阳性制造机。审稿人如何识破:正文用 1% 而附录出现 2%、5% 结果方向相反却不解释。诚实替代:先做 Cook's D/DFBETA(见 A6)诊断哪个点真正驱动系数,再有依据地处理;分位档位全报告。

stata · A4_极端值.do
* A4 winsor2 压回 vs trim 删除;可 by(Year)/by(Ind) 分组
* ssc install winsor2
clear all
set seed 404
set obs 2000
gen year = 2010 + mod(_n,10)
gen ind  = ceil(runiform()*20)
gen x = rnormal()
replace x = 50 in 1/20                 // 20个极端值
gen y = 0.3*x + rnormal(0,1.5)

* 压回(winsor):保留观测数,把尾部压到分位
winsor2 x, cuts(1 99) suffix(_w)
* 按年份分组缩尾(消除跨年量纲漂移)
winsor2 x, cuts(1 99) suffix(_wy) by(year)
* 按行业分组缩尾
winsor2 x, cuts(1 99) suffix(_wi) by(ind)

reg y x      ; est store raw
reg y x_w    ; est store w1
reg y x_wy   ; est store w_year
esttab raw w1 w_year, keep(x x_w x_wy) b(%9.3f) se star(*.1 **.05 ***.01)
* 红线:不要从 cuts(1 99)/(2 98)/(5 95) 里挑一个显著的写正文

A5先取对数还是先缩尾:顺序不同,结果不同

是什么:财务变量通常要 ln(1+x) 又要缩尾,但"先 log 后 winsor"与"先 winsor 后 log"是两道不同的工序。机制:对数把右偏分布压对称,再缩尾压的是对数后的尾部;先缩尾压的是原始尺度的尾部,两者落在数据上的切点完全不同,系数会有可见差异。合法性判别:这本身不是红线,但它是一个被低估的自由度——你不能把两种顺序都跑一遍、挑显著的那种写论文。审稿人如何识破:数据附录里变量构造顺序含糊,"对数化与缩尾处理"一句带过。诚实替代:在数据清洗章节固定并写死 pipeline("先对连续变量在 1%/99% 缩尾,再取自然对数"),顺序不随结果变动;两种顺序都稳健的结果更可信,可作附录。

stata · A5_顺序.do
* A5 先 log 还是先 winsor:固定 pipeline,不要试
clear all
set seed 505
set obs 3000
gen rev = exp(rnormal(3,1.5))          // 右偏的营收
gen x   = rnormal()
gen y   = 0.2*x + 0.1*ln(rev+1) + rnormal()

* 顺序1:先缩尾后 log
winsor2 rev, cuts(1 99) suffix(_w)
gen ln_rev1 = ln(rev_w + 1)
* 顺序2:先 log 后缩尾
gen ln_rev0 = ln(rev + 1)
winsor2 ln_rev0, cuts(1 99) suffix(_w)

reg y x ln_rev1   ; est store order1
reg y x ln_rev0_w ; est store order2
esttab order1 order2, b(%9.3f) se
* 把你采用的那套顺序写进数据清洗章节,另一套放附录即可

A6影响诊断:Cook's D / DFBETA / leave-one-out

是什么:predict, cooksddfbetaleave-one-out 找出"删掉它整个拟合会大变"的观测。机制:极端值(x 或 y 离群)不等于有影响力观测——真正牵着 OLS 走的是同时高杠杆、高残差的点。合法性判别:影响诊断是合法工具:发现某点 Cook's D>4/N 且经查是录入错误(如多打一个零),有明确理由删除并说明。但如果用它按对核心系数的贡献排序、系统性删除让系数不显著的点,就越过红线进入 F1。审稿人如何识破:删掉的点没有任何数据错误记录、删除数量与位置随迭代变化。诚实替代:诊断出问题点后,要么修正数据错误,要么把"含/不含该点"两列并列;样本定义分析前确定。

stata · A6_影响诊断.do
* A6 Cook's D / DFBETA:极端值≠有影响力
clear all
set seed 606
set obs 1200
gen id = _n
gen x = rnormal()
replace x = 12 in 1/5                  // 5个高杠杆点
gen y = 0.3*x + rnormal(0,1.5)

reg y x
predict cook, cooksd                   // Cook's D > 4/N 视为高影响
predict lev, leverage
dfbeta                                 // 逐点删去后 x 系数变化
list id x y cook if cook > 4/_N

* 合法:经查是错误观测,有依据地剔除
reg y x if cook <= 4/_N
* 红线方向:把"按 b_x 排序删观测"做成循环(见 F1)——切勿使用

03 B 类 · 变量与测量操作(5 种)

B1控制变量组合:Model1→Model2→Model3

是什么:从"只放核心解释变量"逐步加入企业层面、行业层面、宏观层面控制,用 esttab 输出 Model1–3 对比。机制:加控制变量同时做三件事——改变遗漏变量偏误、改变共线性(坏控制/对撞控制会引入偏误)、以及因为新控制变量有缺失值而悄悄改变样本合法性判别:控制集由理论与文献惯例决定、逐级报告、无论核心系数是否显著都照报,合法;按 p 值逐个试加控制变量,直到核心变量变显著,是经典数据挖掘。审稿人如何识破:Model1 不显著、Model3 突然三颗星、加入的那个"救命"控制变量与论文叙事关系牵强。诚实替代:事前确定基准控制集;逐步加入仅用于展示稳健性;注意每加一个控制 N 是否变化并说明。

stata · B1_控制变量.do
* B1 控制变量逐级加入,esttab 输出 Model1-3
clear all
set seed 707
set obs 1500
gen x = rnormal()
gen c1 = rnormal()                      // 企业控制
gen c2 = rnormal()                      // 行业控制(制造缺失)
replace c2 = . in 1/200
gen y = 0.25*x + 0.3*c1 + 0.5*c2 + rnormal()

reg y x                              ; est store m1
reg y x c1                           ; est store m2
reg y x c1 c2                        ; est store m3
esttab m1 m2 m3, keep(x c1 c2) b(%9.3f) se star(*.1 **.05 ***.01) ///
    mtitles("Model1 无控制" "Model2 企业控制" "Model3 全控制")
* 注意 m3 的 N 比 m2 小200(因 c2 缺失)——正文必须写明
* 红线:逐格试 c1..c10 哪个加进去 x 就显著,只留那个

B2核心变量的定义方式:水平/变化/滞后/比例/0-1/阶段

是什么:同一个"政策冲击",可以用水平值、一阶差分(变化率)、滞后项、占 GDP 比例、是否实施的 0-1 虚拟、或"实施前/中/后"阶段变量来测。机制:换一种操作化,往往等于换了一个被识别的参数——阶段异质性不是"把 p 调小",而是在回答另一个问题。合法性判别:事前理论给出核心变量的主定义,其余定义作为稳健性;把"水平、变化、比例、虚拟"五六种全部跑一遍只挑显著的写正文,红线。审稿人如何识破:变量定义在引言与稳健性里来回切换、不同定义下系数方向都变了却只讨论显著那张。诚实替代:主定义事前锁定;多操作化结果做成一张稳健性表,方向一致才称"稳健",方向不一就如实讨论。

stata · B2_核心变量定义.do
* B2 核心变量多种操作化,事前锁定主定义
clear all
set seed 808
set obs 1200
gen id = ceil(_n/6)
gen year = 2010 + mod(_n,6)
xtset id year
gen policy = rnormal()
gen y = 0.2*l.policy + rnormal()

gen policy_l1 = l.policy               // 滞后一期
gen policy_d  = d.policy               // 一阶差分
gen policy_dum = policy>0              // 0-1 虚拟
gen policy_stage = cond(year<=2012,0,cond(year<=2015,1,2))  // 阶段

reg y policy      ; est store def_level
reg y policy_l1  ; est store def_lag
reg y policy_d    ; est store def_diff
reg y i.policy_stage#c.policy        ; est store def_stage
esttab def_level def_lag def_diff, b(%9.3f) se star(*.1 **.05 ***.01)

B3变量变换:ln / 人均 / 比率 / 增长率 / 标准化 / 连续→分类

是什么:对 X 或 Y 取对数、除以人口换算成人均、换成比率或增长率、z-score 标准化、或把连续变量切成高中低三组。机制:要区分两类变换——改善分布(log 把右偏压对称、标准化便于跨变量比较,不改变你在测什么)与改变测量构念(GDP 换成人均 GDP、连续政策强度换成"是否实施",回答的是不同问题)。合法性判别:log、标准化合法;连续变量为了"造出一个显著断点/分组"而硬切分类(如把融资约束在中位数切一刀,试多个切点),是红线。审稿人如何识破:分组切点在论文中随稳健性表漂移。诚实替代:连续变量主回归用连续形式;分组仅用于叙事性异质性,切点事前定(中位数、三分位)并用交互项检验。

stata · B3_变量变换.do
* B3 改善分布(log/标准化) vs 改变构念(连续切分类)
clear all
set seed 909
set obs 1500
gen x_raw = exp(rnormal(0,1))          // 右偏
gen y = 0.3*ln(x_raw) + rnormal()

* 合法:log 改善分布
gen ln_x = ln(x_raw)
reg y ln_x
* 合法:标准化
sum ln_x
gen z_x = (ln_x-r(mean))/r(sd)
reg y z_x
* 红线方向:在10/25/50/75分位数上逐个试切点
* xtile x_bin = x_raw, nq(2)  // 切点必须事前定,不能事后挑

B4变量量级 / 单位 / 倒数处理(逆向指标正向化)

是什么:把"融资成本"换成"融资可得性"、用 1/x 或负号把逆向指标转为正向、把万元换成亿元。机制:单位只影响系数大小不影响 t 值;但逆向指标的符号直接决定系数正负与星号方向。合法性判别:逆向指标正向化是常规、必须在变量构造节事前定义;为了让故事"方向好看"而反复在正向/负向定义间切换,红线。审稿人如何识破:同一变量在不同表里一会叫"成本"一会叫"便利"、符号忽正忽负。诚实替代:每个变量给出唯一、事前的方向定义与计算公式;稳健性不改变方向定义。

stata · B4_逆向指标.do
* B4 逆向指标正向化:事前定义一次,不再改
clear all
set seed 111
set obs 1000
gen cost = rnormal(0,1)                 // 融资成本(越高越差)
gen y = -0.3*cost + rnormal()           // 成本越高,y越低

* 事前定义:融资便利 = -成本(正向指标)
gen ease = -cost
reg y ease                              // 预期为正,与故事一致
* 红线:为了"系数显著为负",有时报 cost 有时报 -cost

B5企业年龄控制:上市年限 / 成立年限取对数 +1

是什么:控制企业年龄时,常用 gen age = year - listyear(上市年限)或成立年份差,并取 ln(1+age) 缓解偏态。机制:年龄通常右偏(大量年轻企业、少数老牌企业),不取对数时极端老企业会拉大 SE;取 ln(1+age) 让分布更对称。合法性判别:这是常规做法,本身不涉红线;要注意的是"上市年限"与"成立年限"是两个不同构念,不能哪个显著用哪个。审稿人如何识破:变量名含糊为"企业年龄",实则在两套口径间游移。诚实替代:写明用上市年限还是成立年限;主口径一种,另一种作稳健性。

stata · B5_企业年龄.do
* B5 企业年龄控制:ln(1+age)
clear all
set seed 222
set obs 2000
gen listyear = 1990 + floor(runiform()*30)
gen year = 2020
gen age = year - listyear               // 上市年限
gen lnage = ln(1+age)                   // 取对数+1 缓解偏态
gen x = rnormal()
gen y = 0.2*x - 0.01*age + rnormal()
reg y x age
reg y x lnage                           // 推荐:对数化后更稳健

04 C 类 · 模型与估计操作(6 种)

C1换估计模型:OLS / logit / probit / xtlogit / reghdfe / stcox / Poisson / negbin

是什么:因变量是 0-1 用 logit/probit,面板二值用 xtlogit,计数用 Poisson/negbin,生存数据用 stcox,连续用 OLS/reghdfe。机制:不同估计量对分布假设、异质性处理、小样本偏误的处理不同;FE logit 只用组内变异,丢弃组间信息,系数可能与 pooled logit 差很多。合法性判别:模型选择应由因变量性质(连续/二值/计数/生存)与理论决定;把 OLS、logit、probit、Poisson、negbin 全跑一遍挑显著的,红线。审稿人如何识破:二值因变量正文用 OLS 却在附录换成 logit 才显著。诚实替代:主模型按因变量性质选;其他模型作为稳健性全报告;边际效应要换算出来比较。

stata · C1_换模型.do
* C1 按因变量性质选模型,不要试
clear all
set seed 333
set obs 1500
gen id = ceil(_n/5)
gen x = rnormal()
gen y_latent = 0.5*x + rnormal()
gen y_bin = (y_latent>0)                // 二值因变量
gen y_count = poisson(0.6+0.4*x)        // 计数因变量

reg y_bin x        ; est store ols_lpm      // LPM(可作稳健性)
logit y_bin x      ; est store logit
probit y_bin x     ; est store probit
xtset id
xtlogit y_bin x, fe                         // FE logit 只用组内
poisson y_count x  ; est store poisson
nbreg y_count x    ; est store negbin
esttab ols_lpm logit probit, b(%9.3f) se star(*.1 **.05 ***.01)

C2固定效应组合:year / firm / country / industry / 交互固定效应

是什么:reghdfe y x, absorb(Year Ind2) 吸收年份、企业、国家、行业,或双向/三向交互固定效应(country×year、industry×year)。机制:每加一层 FE,吸收掉那一层的不可观测异质性,但也消耗自由度、改变识别来源(从截面变异变成只靠企业内时序变异)。合法性判别:FE 组合由经济结构决定(面板企业数据通常双向 FE);逐个加 FE 直到核心变量"恰好显著",是红线边缘。审稿人如何识破:FE 层级在稳健性表里跳来跳去、系数符号随 FE 增加而翻转。诚实替代:基准 FE 事前定;从少到多逐级报告,观察系数稳定区间。

stata · C2_固定效应.do
* C2 固定效应组合:reghdfe 吸收多维 FE
clear all
set seed 444
set obs 2000
gen firm = ceil(_n/10)
gen year = 2010 + mod(_n,10)
gen ind  = ceil(runiform()*15)
gen x = rnormal() + 0.3*rnormal(ind)    // 行业层面冲击
gen y = 0.3*x + rnormal(firm) + rnormal(year)

reghdfe y x, absorb(firm) vce(cluster firm)            ; est store fe_firm
reghdfe y x, absorb(firm year) vce(cluster firm)       ; est store fe_2way
reghdfe y x, absorb(ind#year) vce(cluster ind)         ; est store fe_indyear
esttab fe_firm fe_2way fe_indyear, keep(x) b(%9.3f) se star(*.1 **.05 ***.01)

C3行业代码粒度:i.Ind1 / i.Ind2 / i.Ind3

是什么:用一位/两位/三位行业代码分别作为固定效应或聚类层级:i.Ind1i.Ind2i.Ind3机制:粒度越细,吸收的行业异质性越细,但聚类数随之变化、标准误自由度改变;聚类层级从一位变三位,SE 可能从显著变不显著。合法性判别:不同粒度作为稳健性报告合法;挑"恰好显著"的粒度写正文,红线。审稿人如何识破:正文用两位行业 FE,附录换成三位才显著却不解释。诚实替代:按国民经济行业分类惯例选定基准粒度,各粒度稳健性并列。

stata · C3_行业粒度.do
* C3 行业代码粒度 Ind1/Ind2/Ind3
clear all
set seed 555
set obs 2000
gen ind1 = ceil(runiform()*20)          // 一位
gen ind2 = ind1*10 + ceil(runiform()*5)// 两位(100个)
gen ind3 = ind2*10 + ceil(runiform()*3)// 三位(300个)
gen x = rnormal()
gen y = 0.3*x + rnormal(ind2) + rnormal()

reghdfe y x, absorb(i.ind1) vce(cluster ind1) ; est store g1
reghdfe y x, absorb(i.ind2) vce(cluster ind2) ; est store g2
reghdfe y x, absorb(i.ind3) vce(cluster ind3) ; est store g3
esttab g1 g2 g3, keep(x) b(%9.3f) se star(*.1 **.05 ***.01)

C4函数形式:线性 / U 型 / 倒 U / 门槛 / 分段 / 调节

是什么:加入二次项 c.X##c.X 识别 U 型/倒 U,加入交互 c.X##i.Stage 识别调节/阶段,或门槛、分段回归。机制:真实关系是非线性时硬套线性,平均斜率≈0 造成"假不显著";加正确函数形式后关系显现。合法性判别:有理论假设 + RESET/图形诊断支持的非线性,合法;盲目试二次、三次、分段、门槛各种形式直到显著,红线。审稿人如何识破:二次项显著但拐点落在数据范围之外、门槛值是搜出来的而非制度给定。诚实替代:事前提出非线性假设;RESET 与 lowess 诊断;报告拐点是否在支撑集内、均值处边际效应。

stata · C4_函数形式.do
* C4 二次项识别 U 型/倒 U;交互识别调节
clear all
set seed 666
set obs 1500
gen x = rnormal(-2,2)
gen y = 1 - 0.4*x^2 + rnormal()        // 真实倒U

reg y x                                 // 线性误设:平均斜率≈0
gen x2 = x^2
reg y c.x##c.x                          // = reg y x c.x#c.x
test x2                                 // 二次项显著=非线性
* 调节/阶段:c.x##i.Stage
gen stage = cond(x<0,0,1)
reg y c.x##i.stage
margins, dydx(x) at(stage=(0 1))       // 两阶段各自边际效应

C5高维固定效应:xtreg 与 reghdfe 对照、R² 分项

是什么:xtreg, fe 只能吸收一维面板 FE;reghdfe 用 Frisch–Waugh–Lovel 残差化吸收多维高维 FE,并汇报 within/overall 及各固定效应贡献的 R²。机制:高维 FE 下 xtreg 要么跑不动、要么吸收不全;reghdfe 的 R² 拆解能告诉你固定效应解释了多少变异。合法性判别:用 reghdfe 合法且高效;但要注意吸收 FE 后实际参与估计的样本可能变少( singleton 组被丢弃),隐瞒这一变化属误导。审稿人如何识破:样本量比 raw data 小很多却不说明 singleton 剔除。诚实替代:reghdfe 后报告 e(N) 与组结构;附 xtreg 对照。

stata · C5_高维FE.do
* C5 xtreg vs reghdfe;R² 分项;singleton 样本
clear all
set seed 777
set obs 3000
gen firm = ceil(_n/20)
gen year = 2010 + mod(_n,10)
gen x = rnormal()
gen y = 0.3*x + rnormal(firm) + rnormal(year)

xtset firm year
xtreg y x i.year, fe                    ; est store xtreg_fe
reghdfe y x, absorb(firm year)          ; est store reghdfe_r2
esttab xtreg_fe reghdfe_r2, keep(x) b(%9.3f) se
* reghdfe 输出会显示 absorbed FE 个数与 R² 分解
* 检查 singleton:被 absorb 掉的单观测组
display "实际估计 N = " e(N)

C6因变量稀有事件:relogit / Firth logit / case-control

是什么:二值因变量里事件(如违约、退市)只占 1–2% 时,普通 logit 系数会严重高估(分离问题),需用 firthlogit(Firth 惩罚似然)或 relogit(King & Zeng 稀有事件 logit 校正)。机制:稀有事件下 MLE 有限样本偏误,系数绝对值被推大。合法性判别:诊断出稀有事件后采用校正模型,合法且更诚实;用普通 logit 硬报一个偏大的"显著"系数,反而是不规范。审稿人如何识破:处理组占比不到 2% 却用普通 logit 报大系数。诚实替代:报告处理组比例;firthlogit/relogit 作稳健性;注意 case-control 抽样下总体效应需重新加权。

stata · C6_稀有事件.do
* C6 稀有事件因变量:firthlogit / relogit
* ssc install firthlogit
clear all
set seed 888
set obs 3000
gen x = rnormal()
gen y_latent = -3 + 0.5*x + rnormal()
gen rare = (y_latent>0)                 // 事件仅约5%

sum rare                                 // 确认稀有程度
logit rare x           ; est store plain_logit
firthlogit rare x, iter(100)            ; est store firth
esttab plain_logit firth, b(%9.3f) se star(*.1 **.05 ***.01)
* 稀有事件下普通 logit 系数通常偏大,firth 更可靠

05 D 类 · 统计推断操作(2 种)

D1标准误与聚类:ordinary / robust / cluster / two-way

是什么:系数 β 不变,但标准误可以从普通 OLS、异方差稳健(robust)、单维聚类(个体/行业)到双向聚类(行业×年份)逐级放宽。机制:t = β / SE,同一个 β,只换标准误算法,p 值就能从 0.02 跳到 0.20——这是所有旋钮里性价比最高、也最容易被滥用的一个。合法性判别:标准误必须按数据的真实相关结构选(误差在哪一层相关就聚到哪一层),聚类数太少(<约 40–50)要用 wild cluster bootstrap;把四种 SE 全试一遍、挑最窄的那个写正文,是审稿人最警惕的红线边缘行为。审稿人如何识破:正文用的是从未在方法论上辩护过的那种 SE;OLS 显著、聚类后立刻不显著却仍宣称"稳健"。诚实替代:在方法论节明确论证聚类层级;四种 SE 同表对比;选最保守且有理论依据的。

stata · D1_标准误.do
* D1 同一系数,四种标准误,p 值天差地别
clear all
set seed 999
set obs 2000
gen firm = ceil(_n/5)
gen ind  = ceil(runiform()*20)
gen x = rnormal()
gen y = 0.3*x + rnormal(ind) + rnormal()   // 同行业残差相关

reg y x, vce(ols)                    ; est store s_ols
reg y x, vce(robust)                 ; est store s_rob
reg y x, vce(cluster firm)           ; est store s_firm
reghdfe y x, absorb(ind) vce(cluster ind) ; est store s_ind
* 双向聚类
reghdfe y x, absorb(ind) vce(cluster ind firm) ; est store s_two
esttab s_ols s_rob s_firm s_ind s_two, keep(x) b(%9.3f) se star(*.1 **.05 ***.01)
* 红线:哪一列最窄就只报哪一列;合法:论证后报告最保守且可辩护的那列

D2加权:country / firm / population / sampling weights

是什么:[pw=weight]pweight 按国家、企业规模、人口或抽样权重估计"目标总体"的平均效应。机制:加权改变每个观测的权重,等于改变你估计的是哪个总体的平均处理效应(ATE);抽样调查里有抽样权重、宏国数据里大国小国权重不同,都会改变 β 和 SE。合法性判别:加权必须有理论或抽样设计支撑,不能因为加权后显著才加。如果研究本身是抽样调查、或理论上要估计总体效应,加权合法且必要。审稿人如何识破:正文突然出现一个前文从未提及的 weight 变量、不加权与加权结果符号相反、权重构造毫无交代。诚实替代:权重的来源(抽样概率倒数、人口权重)事前说明;不加权与加权结果同表报告,解释差异。

⛔ D2 不可逾越的规范线

先跑不加权——不显著;再加一个"人口权重"——显著了;于是正文只报加权版。这是教科书式 p-hacking。权重不是用来调 p 值的旋钮。正确顺序是:抽样设计/理论决定你本来就该加权,无论结果显著与否都加权,并把未加权版作为对照放上桌。

stata · D2_加权.do
* D2 加权:必须有抽样设计/理论依据
clear all
set seed 1010
set obs 1500
gen country = ceil(runiform()*10)
gen pop = runiform()*1000              // 各国人口权重
gen x = rnormal()
gen y = 0.2*x + rnormal(country)

* 不加权:每个国家等权
reg y x
* 人口加权:估计"人口意义上的"平均效应
reg y x [pw=pop]
* 合法:因为目标总体是全球人口加权平均,理论上本就该加权重
* 红线:发现不加权不显著、加权后才显著,就只报加权版

06 E 类 · 时间结构与识别操作(3 种)

E1时间结构 / Lag:X_t→Y_t 不显著,但 X_{t-1}→Y_t 显著

是什么:把解释变量从当期换成滞后一期/二期/三期 L1.x / L2.x / L3.x,或换成移动平均。机制:政策传导、预期调整需要时间,滞后效应可能比当期更合理;但逐期扫描 L1..L5 直到某一期显著,本质是多重检验。合法性判别:滞后阶数必须由经济理论(传导期、财报披露时滞)事前决定;合理性要注意——不能纯靠数据扫出来。审稿人如何识破:只报告 L2 显著、L1/L3 不显著却无任何理论解释为何是二期。诚实替代:事前声明主滞后阶;各阶滞后同表报告;用 AIC/BIC 或理论而非显著性定阶。

stata · E1_滞后.do
* E1 滞后结构:理论定阶,不逐期扫显著
clear all
set seed 1212
set obs 1200
gen id = ceil(_n/6)
gen year = 2010 + mod(_n,6)
xtset id year
gen x = rnormal()
gen y = 0.3*l2.x + rnormal()          // 真实效应滞后两期

reg y x        ; est store lag0        // 当期:弱
reg y l1.x     ; est store lag1
reg y l2.x     ; est store lag2        // 理论预期的传导期
reg y l3.x     ; est store lag3
esttab lag0 lag1 lag2 lag3, b(%9.3f) se star(*.1 **.05 ***.01)
* 合法:理论说"政策两期后起效",主报 L2,其余稳健性
* 红线:L1..L5 全扫一遍,哪个星多报哪个

E2平行趋势不通过:事件研究与"观测值合并检验"

是什么:DID 中事件研究图显示事前趋势不平行时,常见"补救"包括合并处理时点、剔除事件前异常期、把多个政策事件合并成一个处理强度变量。机制:平行趋势是 DID 识别的核心假设;事前趋势显著本身就是在告诉你"这组比较不可比",合并事件窗口可能掩盖问题。合法性判别:如果事前确有制度上合理的事件合并依据(多批次政策、统一政策实施),合并并报告动态效应合法;仅仅因为不合并就不显著、合并后才平行,则是掩盖识别失败。审稿人如何识破:事件研究图被"美化"、前趋势系数被删掉几期、合并处理时点的理由牵强。诚实替代:完整事件研究图(含 pre-trend 全部期);事前趋势检验明确报告;不通过就承认识别受限,换 RDD/IV,而不是缝合趋势。

stata · E2_平行趋势.do
* E2 平行趋势:完整事件研究,不缝合
clear all
set seed 1313
set obs 1500
gen firm = ceil(_n/5)
gen year = 2005 + mod(_n,10)
gen treat = (firm>100)
gen post  = year>=2012
gen x = rnormal()
gen y = 0.4*treat*post + 0.2*treat*(year-2012) + rnormal()  // 事前就有趋势

* 事件研究:相对政策年的虚拟变量
gen rel = year - 2012
forvalues k=-4/3 {
    gen e`k' = treat*(rel==`k')
}
reghdfe y e-4(1/0) e1 e2 e3, absorb(firm year) vce(cluster firm)
* 看 e-4..e-1 是否显著(若显著=平行趋势不通过)
* 合法:报告全部事前系数;红线:只画 e0 之后的部分"显得平行"

E3逐步回归选控制变量:按显著性逐步加入

是什么:stepwise 或手工按 p 值逐个加入控制变量,直到核心变量最显著。机制:这是把"模型选择"完全交给 p 值,等价于在上百个候选控制里反复试。合法性判别:这是红线——教科书级数据挖掘。逐步回归选出的"显著"系数,其假阳性率远超标称水平,且系数标准误严重低估(没有考虑模型选择本身的不确定性)。审稿人如何识破:论文方法节写"采用逐步回归筛选控制变量",或控制集与文献惯例脱节。诚实替代:控制集由理论与文献事前决定;模型选择的不确定性用规范贝叶斯/交叉验证(如 DML)处理;绝不用 p 值选控制。

stata · E3_逐步回归.do
* E3 逐步回归:红线演示,仅用于理解其风险
clear all
set seed 1414
set obs 1200
gen y = rnormal()
* 制造20个纯噪声控制变量
forvalues j=1/20 {
    gen c`j' = rnormal()
}
gen x = rnormal() + 0.2*c1
replace y = y + 0.1*x

* (红线)按 p 值逐步加入控制:会把噪声变量也选进来
stepwise , pe(0.05): reg y x c1-c20
* 观察:被选入的控制变量里混着纯噪声,核心 x 的 p 值被玩弄
* 诚实替代:理论事前定控制集,如 reg y x c1 c3 c7
reg y x c1 c3 c7

07 G 类 · DID 与因果识别诊断(6 种)

ℹ 这一类与前面 A–E 类性质不同

A–E 类讲的是"哪些旋钮能把 p 值拧来拧去";G 类讲的是识别本身可不可信。平行趋势是 DID 的不可检验假设——你只能用政策前数据"诊断"它,永远不能"证明"它通过。把 G 类当成"体检报告":体检正常不能保证没病,体检异常也不一定就没救,但体检报告必须如实、完整地交出来。与姊妹页 07 DID 双重差分 配合阅读。

G1事件研究图(event study plot):leads/lags 系数 + 95% 置信带

是什么:把 DID 展开成动态形式,估计政策前 $|k|$ 期(leads)与政策后 $k$ 期(lags)的相对效应 $\beta_k$,并画成带 95% 置信带的系数图;通常省略 $k=-1$ 为基准期。为什么改变显著性/可信度:事件研究图是平行趋势假设的图形诊断——pre 期系数若贴着 0、置信带跨 0,图形上支持平行趋势;若 pre 期系数已经单调漂移,即使交互项 $\hat{\beta}_{DID}$ 显著,识别也站不住。它同时回答"效应是立即出现还是渐次累积"。Stata 代码:见下方 eventdd / reghdfe 手写 leads-lags / csdid 三种实现。合法性判别:必须报告全部事件期(含最远 leads 与最远 lags),基准期选择事前定;只挑 pre 期里"看起来平"的那几期画进正文、把漂移严重的远端 leads 裁掉,是红线。审稿人如何识破:图的横轴起点"恰好"从政策前 2 年才开始、远端 leads 神秘消失、正文从未说明基准期为什么是 $k=-1$。诚实替代:主图全期报告;窗口选择(如 $[-5,+5]$)在数据收集阶段就由样本长度与制度窗口决定,并在附录给"换窗口仍稳健"的版本。

stata · G1_event_study.do
* G1 事件研究图:eventdd 一键 vs reghdfe 手写 leads/lags
* ssc install eventdd, replace
* ssc install coefplot,  replace
clear all
set seed 2301
set obs 600
gen id = ceil(_n/6)
gen year = 2005 + mod(_n,10)
gen g = cond(id<=60, 2012, 0)            // 前60个2012年处理,其余never-treated
xtset id year
gen treat = (g!=0 & year>=g)
gen rel = year - g if g!=0
gen y = 0.8*treat + rnormal(id) + rnormal(year) + rnormal()

* 方法1:eventdd 一键出图(含95% CI)
*   lead(4) lag(3) :政策前4期、政策后3期
*   baseline(-1)  :以 k=-1 为基准
*   accum(.)      :pre期系数自动汇总
eventdd y i.year, timevar(rel) lead(4) lag(3) baseline(-1) ///
    controls(i.id) cluster(id) graph_op( ///
    yline(0, lcolor(red)) xline(0.5, lpattern(dash)) ///
    title("事件研究图:leads/lags 与95%置信带") ///
    ytitle("估计系数") xtitle("相对政策时点 k"))

* 方法2:reghdfe 手写 leads/lags(更透明,推荐主回归用)
forvalues k=-4/3 {
    local kk = `k' + 100
    gen e`kk' = (rel==`k') if g!=0
    replace e`kk' = 0 if g==0
}
* 省略 e099 (即 k=-1) 作为基准
reghdfe y e096 e097 e098 e100 e101 e102 e103, ///
    absorb(id year) vce(cluster id)
* e096=k=-4, e097=k=-3, e098=k=-2, e100=k=0...
coefplot, keep(e096 e097 e098 e100 e101 e102 e103) vertical ///
    yline(0) xline(4.5, lp(dash)) ///
    order(e096 e097 e098 e100 e101 e102 e103) ///
    title("手写 leads/lags 事件研究图")
* 看图:pre期 e096/e097/e098 应贴0;post期 e100..e103 应显著为正

G2pre-trend 联合 F 检验与 pretrends(Roth 2022):不能把"不显著"当"平行趋势成立"

是什么:把政策前所有 leads 系数联合做 Wald/F 检验 test e096 e097 e098;更现代的做法是 Roth (2022, JoE) 的 pretrends 命令,它不仅做联合检验,还估计"即使存在真实 pre-trend,你这篇论文的检验有多大功效能把它抓出来"。为什么改变显著性/可信度:这是 G 类最容易被误用的一点——pre 期系数不显著,绝不等于平行趋势成立。Roth 证明:在大多数实务样本里,pre-trend 联合检验的功效常常只有 30–50%,也就是说即使真的存在会让你结论严重偏误的趋势漂移,你也有一半以上的概率"抓不到"。把"p=0.21 不显著"写成"平行趋势成立",是中文顶刊被审稿人拒稿的高频理由。Stata 代码:见下方。合法性判别:报告联合检验 p 值是必要的;但 p>0.05 后必须配合 pretrends 做功效分析,并在文中明确说"我们不能拒绝平行趋势,但受限于 pre-trend 检验功效较低,结论需谨慎"。审稿人如何识破:只写"平行趋势检验通过(p=0.18)"却不做功效分析、样本量小到 leads 系数标准误大到离谱还宣称"通过"。诚实替代:同时报告 (i) 图形 event study;(ii) 联合 F 检验;(iii) pretrends 估计的"可检测的最小 pre-trend 斜率";(iv) 若功效低,做 Roth & Rambachan 式的敏感性分析(允许 pre 期存在一定幅度偏离时,post 效应的 CI 还跨不跨 0)。

stata · G2_pretrends_roth.do
* G2 pre-trend 联合检验 + Roth (2022) pretrends 功效分析
* ssc install pretrends, replace
* 沿用 G1 模拟数据:reghdfe 后已有 e096(k=-4) e097(k=-3) e098(k=-2)

* 1) 朴素做法:pre 期 leads 联合 F 检验
reghdfe y e096 e097 e098 e100 e101 e102 e103, ///
    absorb(id year) vce(cluster id)
test e096 e097 e098          // H0: pre期系数全=0
* 若 p>0.05,只能说"不能拒绝平行趋势",不能说"平行趋势成立"

* 2) Roth (2022) pretrends:自动评估检验功效
*    pretrends 会:
*      - 自动识别 pre 期虚拟变量
*      - 估计"如果真实存在线性 pre-trend,本检验有多大概率抓住"
*      - 报告 " detectable bias " —— 在当前功效下,
*        多大的 pre-trend 漂移才会被检测到
*   语法(在 event study 回归之后跑):
* pretrends, leads(4) lag(0) post(3)
*   输出关键量:
*     Power of pre-trend test (5% level) ≈ 0.3x
*     Partial R^2 of pre-trend ...
* 解读:
*   - 若 power 只有 0.35:意味着真实 pre-trend 即使把你的
*     ATT 偏误 20%,你也有 65% 概率检验不出来。
*   - 论文写法:
*     "We fail to reject parallel trends (joint F p=0.21),
*      but the pre-trend test has limited power (~35% for a
*      trend that would bias ATT by 20%), so we additionally
*      report Rambachan-Roth sensitivity bounds."

* 3) 观测量合并检验:当某事件期观测太少(如远端 leads 只有
*    20 个处理组),单独系数 SE 巨大,应合并相邻期:
*    例如把 k=-4 与 k=-3 合并成 "leads early"
gen e_pre_early = (rel<=-3) if g!=0
replace e_pre_early = 0 if g==0
reghdfe y e_pre_early e098 e100 e101 e102 e103, ///
    absorb(id year) vce(cluster id)
* 注意:合并必须在看结果前由"该期观测太少"这一客观理由决定,
*      不能发现合并后"恰好平行"才合并。

G3安慰剂检验(placebo test):虚构处理时间 / 虚构处理组

是什么:三种合法 placebo:(i) 虚构处理时间——把政策时点往前提 3–5 年(如真实政策 2012,伪时点 2007),重新跑 DID,伪效应应≈0;(ii) 虚构处理组——从未处理组里随机抽一批当"伪处理组",真实对照组当"伪处理后",重复 500/1000 次画系数分布;(iii) 伪结果变量——用理论上不受政策影响的变量(如性别、年龄)当 Y,应不显著。为什么改变显著性/可信度:placebo 检验回答的是"你估计到的效应是不是来自一个根本不存在的处理"。真实系数应落在 placebo 分布的尾部(<5% 或 >95% 分位)。Stata 代码:见下方。合法性判别:placebo 是合法且推荐的诊断;但如果把伪时点从 1998 扫到 2010,挑一个"刚好不显著"的伪时点写进论文,就退化成 p-hacking。伪时点必须事前选定(通常是政策前最早的 1–2 个伪时点,或直接用随机化 500 次分布)。审稿人如何识破:只做一个 placebo 伪时点、且这个时点的选择理由牵强;500 次随机化的分布图里真实系数其实落在 placebo 分布中部,却只报告"均值≈0"不提分位数。诚实替代:同时做 (i) 政策前最早一个伪时点 + (ii) 500–1000 次随机分配处理组的系数分布图 + (iii) 报告真实系数在 placebo 分布中的分位;三种 placebo 互相印证。

stata · G3_placebo.do
* G3 安慰剂检验:伪时点 + 伪处理组随机化
* 沿用 G1 模拟数据
clear all
set seed 2303
set obs 600
gen id = ceil(_n/6)
gen year = 2005 + mod(_n,10)
gen g = cond(id<=60, 2012, 0)
xtset id year
gen treat = (g!=0 & year>=g)
gen y = 0.8*treat + rnormal(id) + rnormal(year) + rnormal()

* (a) 虚构处理时间:把政策时点提前到 2008(伪政策)
*     若 2008 版 DID 显著,说明 pre-trend 或隐藏趋势存在
gen treat_fake = (g!=0 & year>=2008)
reghdfe y treat_fake, absorb(id year) vce(cluster id)
* 期望:treat_fake 系数不显著(因为真实政策是 2012)
* 若显著 → 平行趋势可疑

* (b) 随机分配伪处理组:500 次蒙特卡洛
permute treat, reps(500) seed(2303) ///
    saving("placebo_dist.dta", replace): ///
    reghdfe y treat, absorb(id year) vce(cluster id)
* 真实系数 0.8 应落在 placebo 分布的 95% 分位之外
use "placebo_dist.dta", clear
sum _b_treat, detail
* 查看 p10/p50/p90 分位;真实 0.8 若在 p99 右侧 → 安慰剂通过

G4动态效应检验:post 期系数的趋势

是什么:政策后 $k=0,1,2,3,\dots$ 的系数 $\beta_k$ 是否随时间单调、是否显著,回答"效应是一次性脉冲还是渐次累积/衰减"。为什么改变显著性/可信度:post 期系数的形状本身就是识别可信度的证据——如果政策当年就跳上去、之后逐年衰减到 0,可能是预期效应或临时冲击;如果政策后 3 年才开始显著且单调上升,可能是传导滞后,也可能是 pre-trend 没洗干净。Stata 代码:在 G1 事件研究图基础上,对 post 期系数做联合显著性与线性趋势检验。合法性判别:动态效应的叙事必须在看结果之前由制度/理论给出预期(如"补贴政策当年起效,第 2 年峰值,第 3 年起稳态");跑出来后发现"只有 k=2 显著"才回头编"政策传导需要两年"的故事,是事后叙事。审稿人如何识破:正文只挑 post 期中显著的那一两个 $k$ 讲故事,其余 post 期系数在附录里方向相反却不提。诚实替代:报告全部 post 期系数的表 + 图;动态效应的经济机制在引言部分就写好(预期 vs 即时 vs 渐次);若实际形状与预期不符,如实讨论而非挑选。

stata · G4_dynamic.do
* G4 post 期动态效应:联合显著 + 趋势
* 沿用 G1 回归:e100=k=0, e101=k=1, e102=k=2, e103=k=3
reghdfe y e096 e097 e098 e100 e101 e102 e103, ///
    absorb(id year) vce(cluster id)

* (i) post 期联合显著性
test e100 e101 e102 e103
* (ii) post 期线性趋势:e101+2*e102+3*e103 是否单调
test (e101 - e100) = (e102 - e101) = (e103 - e102)
* 若拒绝 → post 期不是线性单调,需解释曲线形状

* 诚实写法:把 e100..e103 全部列在主回归表里,
* 不要只挑 e101 一个显著系数说"政策第2年起作用"。

G5交叠 DID 下的 pre-trend 诊断:csdid / did_imputation / eventstudyinteract

是什么:政策分批推开(staggered DID)时,传统 TWFE 事件研究图的 leads 系数本身会被异质性处理效应污染(见 07 DID 页 s4–s5),不能直接拿 TWFE 的 leads 做 pre-trend 检验。必须用新估计量在"干净对照"基础上重做事件研究。为什么改变显著性/可信度:Roth (2022) 与 Roth et al. (2023) 反复强调:交叠 DID 下,TWFE 事件研究图的 pre 期系数即使全部贴 0,也可能只是负权重相互抵消的假象;必须用 csdid / eventstudyinteract / did_imputation 输出的"干净"事件期系数再做 pre-trend 诊断。Stata 代码:见下方。合法性判别:交叠 DID 论文只跑 TWFE + 一张"看起来平"的事件研究图,已经达不到 2024 年后中文顶刊的规范;必须至少有 csdid 的 estat event 输出 + pre 期 leads 联合检验。审稿人如何识破:正文是 TWFE 事件研究图,附录才出现 csdid;csdid 的 event 图里 pre 期其实已经漂移,却只字未提。诚实替代:主回归 csdid,附 estat event 图 + pre 期 leads 联合检验 + pretrends 功效分析;TWFE 只作对照列。

stata · G5_staggered_pretrend.do
* G5 交叠 DID 的 pre-trend 诊断:csdid 事件期 leads 联合检验
* ssc install csdid, replace
* ssc install drdid,  replace
clear all
set seed 2305
set obs 200
gen id = _n
* 三队列:g=2008 (50个), g=2012 (50个), g=0 never-treated (100个)
gen g = cond(_n<=50, 2008, cond(_n<=100, 2012, 0))
expand 11
bysort id: gen year = 1999 + _n
xtset id year
gen treat = (g!=0 & year>=g)
gen y = 0.8*treat + rnormal(id) + rnormal(year) + rnormal()

* csdid 主估计
csdid y, ivar(id) time(year) gvar(g) method(dripw)
* 事件时间聚合(含 leads/lags)
estat event
* csdid_plot 画干净的事件研究图(不含负权重污染)
csdid_plot, title("csdid 事件研究图(交叠 DID 专用)") ///
    legend(off) yline(0)

* 关键:在 csdid 输出上做 pre 期 leads 联合检验
*   estat event 返回的系数按事件期排列;
*   pre 期(k<0)系数联合为 0 的检验
* 实务写法:
*   "We report the pre-trend joint test from csdid:
*    the leads k=-4..-1 are jointly insignificant
*    (Wald p=0.31), and pretrends (Roth 2022) indicates
*    power of approximately 45% to detect a trend that
*    would bias ATT by 20%."
*
* 对照:传统 TWFE 事件研究图在此处会被污染,
*       不能作为交叠 DID 的 pre-trend 证据。

G6平行趋势不通过时:诊断原因与合法处理方案

是什么:pre-trend 显著后,常见诊断与合法补救路径。可能原因:(i) 处理时机内生(政策挑了本来就在变化的地区先试点);(ii) 时变混杂(处理组与对照组面临不同的宏观冲击);(iii) 交叠 DID 的负权重把 pre 期污染。合法方案:局部窗口(local window)——只取政策前后 ±2~3 年,缩短 pre-trend 暴露;② Rambachan-Roth 敏感性界——允许 pre 期存在一定幅度偏离时,post 效应的 CI 范围;③ 合成 DID / synthetic control——若对照组找不到,用合成控制构造反事实;④ Bacon 分解 + 组别-时期估计——找出是哪个队列在污染 pre-trend;⑤ C-S 匹配/加权——csdid 的 covariates 选项做协变量平衡;⑥ 合并观测量——某事件期观测太少时合并相邻期(见 G2);⑦ 如实报告 + 敏感性分析——承认平行趋势受限,把结论限定为"相关性 + 诊断性证据"而非强因果。

⛔ G6 红线:为"凑通过"而事后改窗口/合并分组/选择性报告

审稿人识破手段:① 要求全部事件期系数表——只画显著性好的那几期图藏不住;② 要求原始数据与代码复现——事后改窗口的痕迹在 do 文件里一目了然;③ 问"你为什么选 ±3 年窗口而不是 ±5 年?"——答不出制度/理论依据即露馅;④ 要求 pretrends 功效报告——低功效下宣称"通过"是自相矛盾。平行趋势检验不是"调显著"的旋钮,而是识别可信度的体检报告。体检异常不代表结论作废,但篡改体检报告等于学术不端。

stata · G6_when_fail.do
* G6 平行趋势不通过时的合法处理(红线示例注释在内)
* 沿用 G5 模拟数据

* 合法方案1:局部窗口 —— 仅用政策前后±2年
*   窗口必须在看结果前由制度依据决定
preserve
    keep if year>=2006 & year<=2014   // 政策(2008/2012)前后各±4年
    csdid y, ivar(id) time(year) gvar(g) method(dripw)
    estat event
restore

* 合法方案2:csdid 加协变量做条件平行趋势
*   csdid 会按 X 做 IPW 平衡处理组/对照组的可观测特征
csdid y alpha_i gamma_t, ivar(id) time(year) gvar(g) ///
    method(dripw) covariates(alpha_i gamma_t)
estat event

* 合法方案3:Bacon 分解找出污染队列
* bacondecomp y treat, ddetail
* 若"Later T vs Earlier C"权重>0.3,说明某批队列在污染

* 合法方案4:Rambachan-Roth 敏感性界(Stata 中需配合
*   R 包 Honor & Roth, 或手动给出不同 Mbar 下的 CI)
*   Mbar=0 表示严格平行趋势;Mbar=1 允许 pre 期有线性偏离。
*   报告 "Even when Mbar=1, the lower bound of the ATT
*   CI remains positive at 0.21, so our conclusion is
*   robust to modest pre-trend violations."

* ⛔ 红线(严禁):
*   - 先跑全样本 pre-trend 不通过,回头把窗口改成±2年"凑通过"
*   - 把漂移严重的队列从样本里删掉,理由是"该组异常"
*   - 只在正文报"pre-trend 通过",附录才出现不通过的版本
*   审稿人只要你交出全部 event-time 系数 + do 文件,立刻识破。

08 H 类 · 透明度与多重检验(6 种)

这一类不是"旋钮",而是结构性诊断与披露工具。它们的共同特征是:不管你结果显著不显著,都应该做;做了反而让审稿人更信任你,而不是更怀疑你。

H1机制/中介检验与坏控制(bad control)问题

是什么:机制检验(mediation)想识别 X→M→Y 的传导路径;坏控制指把处理后变量(post-treatment variable)或对撞因子(collider)当作控制变量加入回归。为什么改变显著性/可信度:典型坏控制是"政策后才形成的中间变量 M"——控制 M 等于把 X→M→Y 这条因果路上的效应差掉,人为把 X 对 Y 的总效应压小;更糟的是控制对撞因子会引入 collider bias,把本来无关的两个变量强行变得相关。Bullock, Green & Ha (2010) 指出:多数"机制检验"本质上都在做坏控制。Stata 代码:见下方 DAG 判别法。合法性判别:控制变量必须是处理前或前定(pre-determined)变量;处理后变量不能当控制,只能作为"机制证据"单独报告其随处理的变化。审稿人如何识破:控制变量里混入了"政策实施后才可能发生变化"的变量(如"企业生产率"被当作控制去估计"补贴对就业"的效应,而生产率本身就是补贴的结果)。诚实替代:画 DAG 标出哪些是 confounder、哪些是 mediator、哪些是 collider;主回归只放 confounder;机制检验用"X→M"和"M→Y"分开报告,不把 M 塞进 X→Y 的主回归。

stata · H1_bad_control.do
* H1 坏控制识别:处理后变量不能进主回归
clear all
set seed 2311
set obs 2000
gen X = rnormal()
gen U = rnormal()                       // 不可观测混淆
gen M = 0.5*X + U + rnormal()          // 中介:X→M(处理后)
gen Y = 0.4*X + 0.3*M + U + rnormal()   // Y = X + M + U

* 主回归(合法):只控制前定变量,不控制 M
reg Y X U
* 真实总效应 X→Y ≈ 0.4 + 0.3*0.5 = 0.55

* 坏控制(红线):把中介 M 当控制
reg Y X M U
* 系数会从 0.55 掉到 ≈0.4 —— 你"控制掉"了 X→M→Y 这条通路
* 这不是"更严格",是机制偏误

* 合法机制检验:两步法
reg M X U           ; est store stage1   // X→M
reg Y X U           ; est store total    // X→Y 总效应
* 中介效应 = 间接 = total - direct;不要在 Y 回归里放 M

H2异质性分析:事前理论分组 vs 事后挑子样本

是什么:异质性分析(如"国企 vs 民企""东部 vs 西部""高融资约束 vs 低")有两种性质完全不同的做法:事前分组(理论预测某特征会调节效应大小,主回归里用交互项 c.X##i.Htest 组间差异)与事后挑子样本(跑完全样本后,试国企/民企/东部/西部/大企业/小企业,哪组显著就写哪组"异质性")。为什么改变显著性/可信度:事后挑子样本等价于"在子样本里做一次新的假设检验",20 个子样本里总有 1 个 p<0.05;只报那个 = 隐性 p-hacking。Stata 代码:见交互项检验。合法性判别:合法异质性必须 (i) 事前在理论/文献里预测调节方向;(ii) 用交互项在全样本上估计,而不是分样本各跑一次;(iii) 用 test 检验组间系数差异,而不是"一组有星一组没星"。审稿人如何识破:分样本回归表中一组带星一组不带,却没有交互项检验;分组维度在不同表里漂移。诚实替代:全样本交互项 + 组间差异 test;所有维度的异质性结果同表报告,不只写显著的那个故事。

stata · H2_heterogeneity.do
* H2 事前交互项 vs 事后挑子样本
clear all
set seed 2312
set obs 2000
gen X = rnormal()
gen H = runiform()>0.5                  // 异质性维度(事前定义)
gen Y = 0.3*X + 0.1*X*H + rnormal()     // 真实异质性很小

* 合法:全样本交互项 + test 组间差异
reg Y c.X##i.H
test 1.H#c.X                            // 组间差异是否显著
* 关键:即使 test 不显著,也要如实报

* 红线:分样本各跑一次,挑带星的那张讲故事
* reg Y X if H==1   // 国企子样本
* reg Y X if H==0   // 民企子样本
* 两组系数 t=1.65 vs t=2.10,就写"异质性显著"
* 错误:两个独立回归的系数不能直接比;必须用交互项 test。

H3多重检验校正:Bonferroni / Holm / Benjamini-Hochberg (FDR)

是什么:一次研究里检验了 m 个假设(多个因变量、多个子样本、多个滞后阶、多个机制),哪怕每个检验都用 5% 门槛,整体假阳性率会膨胀到 $1-(1-0.05)^m$;m=20 时膨胀到 64%。三种主流校正:Bonferroni:把 α 除以 m(最保守);② Holm:逐步法,比 Bonferroni 略宽松;③ Benjamini-Hochberg (BH/FDR):控制错误发现率(false discovery rate),比 Bonferroni 宽松,现代实证默认。为什么改变显著性/可信度:不校正就报告一堆"显著",等于在犯统计学意义上的"集体性假阳性"。Stata 代码:multprocqs合法性判别:主回归的核心假设不需要校正(只有一个关键检验);多个因变量/多个子样本/多个机制检验必须报告校正后 p。审稿人如何识破:正文一张表里跑了 15 个系数,其中 5 个带星,却不报告任何多重检验校正。诚实替代:主结果单一;探索性分析全报告 + BH 校正后 p;预注册时就规定主假设与次要假设。

stata · H3_multiple_testing.do
* H3 多重检验校正:Bonferroni / Holm / BH-FDR
* ssc install multproc, replace
clear all
set seed 2313
set obs 1500
gen X = rnormal()
* 构造 6 个"因变量",其中 2 个真有信号、4 个纯噪声
forvalues j=1/6 {
    gen Y`j' = cond(`j'<=2, 0.25*X, 0) + rnormal()
}

* 未校正:6 个回归里挑 p<0.05 的报
forvalues j=1/6 {
    reg Y`j' X
    display "Y`j': p=" %6.4n (2*ttail(e(df_r),_b[X]/_se[X]))
}

* 把 6 个 p 值存成矩阵,做三种校正
* multproc 用法示例(按实际输出填 p 向量):
* matrix pvec = (p1,p2,p3,p4,p5,p6)
* multproc, p(pvec) methods(bonferroni holm benjamini)
* 输出:每个原始 p 对应的 Bonferroni/Holm/BH 调整后 p

* 实务建议:
*   - 主假设(1个):不校正
*   - 次要/探索性(6-20个):报告 BH-FDR 校正后 p
*   - Bonferroni 太保守,只在 p 本来就极显著(如 p<.001)时才安全

H4Specification Curve(规格曲线,Simonsohn, Simmons & Nelson 2020)

是什么:把同一个核心结果的所有合理规格(不同控制集、不同缩尾分位、不同聚类层级、不同滞后阶、不同子样本)全部跑一遍,把每个规格的系数与 p 值按系数大小排列成一条曲线;横轴是规格编号,纵轴是系数估计。为什么改变显著性/可信度:specification curve 把"花园分叉路径"完全展开放在桌面上——如果真实效应稳健,整条曲线系数符号一致、大部分显著;如果效应只在少数几个规格里显著,曲线会显示"只有少数规格显著",p-hacking 无所遁形。Stata 代码:Stata 里没有官方命令,需要用循环 + 矩阵收集。合法性判别:specification curve 是最透明、最受审稿人欢迎的稳健性做法;红线是"跑完 spec curve 后只截曲线里显著的那一段写进正文,把整条曲线藏进附录不引用"。审稿人如何识破:正文只报一个主回归 + 3 个稳健性,却声称"结果稳健";真正的 spec curve 应作为正文图或附录全图。诚实替代:定义 10–20 个合理规格(理论/文献驱动,不是 p 值驱动);全曲线报告;报告"中位数系数"与"显著规格占比"。

stata · H4_spec_curve.do
* H4 Specification Curve:Simonsohn et al. (2020)
* 把所有合理规格的系数按大小排成曲线
clear all
set seed 2314
set obs 2000
gen x = rnormal()
gen c1 = rnormal()
gen c2 = rnormal()
gen c3 = rnormal()
gen y = 0.2*x + 0.3*c1 + rnormal()

* 定义规格:是否加 c1/c2/c3、缩尾 1%/5%、聚类/不聚类
* (简化演示:跑 8 个规格)
matrix sc = J(1, 8, .)
local j = 0
foreach cset in " " "c1" "c1 c2" "c1 c2 c3" {
    foreach clu in "robust" "cluster id" {
        local ++j
        quietly reg y x `cset', vce(`clu')
        matrix sc[1, `j'] = _b[x]
    }
}
* 把矩阵列拉成变量,画曲线
matrix list sc
* 横轴 = 规格编号;纵轴 = 系数;一条水平 y=0 线
* 诚实结论:
*   "The specification curve across 8 reasonable
*    specifications shows the median coefficient is 0.21,
*    and 7/8 specifications have the expected sign."
* 红线:只挑 8 个里 1 个显著的写正文,其余不提。

H5样本量 / 功效报告(power analysis)

是什么:事前 power analysis 回答"要检出效应大小 δ,需要多大 N";事后 post-hoc power 回答"我这个样本量,能检出多大效应"。为什么改变显著性/可信度:功效不足(power<0.5)时,即使真效应存在,你也有一半概率检验不出来——把"不显著"写成"无效应"是严重误导。A2 讲的是"N 大了会把小效应刷显著",H5 讲反面"N 小了会把真效应藏起来"。Stata 代码:power 命令。合法性判别:任何"无效应/政策无效"的结论都必须配合事后功效报告;事前 power analysis 在预注册中强制。审稿人如何识破:样本量 200、系数 SE=0.5、点估计 0.15,作者写"政策无影响"——其实功效低到连 0.8 的效应都可能漏检。诚实替代:报告事后功效曲线或"可检测的最小效应量(MDE)";若功效低,把结论从"无效应"改为"在当前样本下不能检出效应"。

stata · H5_power.do
* H5 功效分析:事前 + 事后
* Stata 13+ 内置 power 命令

* 事前:双样本均值差异,要检出 δ=0.3 SD,power=0.8,α=0.05
power twomeans 0, diff(0.3) power(0.8) alpha(0.05)

* 事后:N=200 时,能以 80% 功效检出多大的处理效应?
*   输出 MDE (minimum detectable effect)
power twomeans 0, n(200) power(0.8) alpha(0.05)

* DID 语境下更实用的事后功效:
*   假设 SE(β)=0.15,要 80% 功效、双侧 5%,
*   临界 t≈1.96+0.84=2.80,MDE = 2.80*0.15 = 0.42
*   含义:只有真实 |ATT|>0.42,你才有 80% 概率检出。
*   若你的点估计是 0.15,诚实写法:
*   "We cannot rule out an effect as large as 0.42
*    with 80% power; our null result should not be
*    interpreted as evidence of no effect."

H6置信区间与等价检验(TOST, two one-sided tests)

是什么:"不显著"≠"无效应"。TOST 是一种试图证明效应足够小的检验:先在事前设定一个"等价界值 δ"(如 |效应|<0.1 即视为实际等价于 0),然后做两个单侧检验——H0: β≥δ vs H1: β<δ,以及 H0: β≤−δ vs H1: β>−δ;两个都拒绝才称"在 ±δ 内等价于 0"。为什么改变显著性/可信度:直接把 p=0.34 写成"政策无影响"是统计学错误;正确的"无效应"声明必须用 TOST 或 CI 落在 ±δ 内。Stata 代码:ttost(ssc install ttost)。合法性判别:等价界值 δ 必须事前由经济意义决定(如"效应小于 0.05 个 SD 即无经济意义"),不能事后挑一个让自己通过的 δ。审稿人如何识破:不显著就写"无效应"、从不报 CI 范围、从不报等价界值。诚实替代:主结果永远报系数 + 95% CI;若要声称"无效应",做 TOST 并报告 δ 的选择依据;把"不显著"严格表述为"在当前样本与功效下不能拒绝零假设"。

stata · H6_TOST.do
* H6 TOST 等价检验:把"不显著"升级为"统计上等价于0"
* ssc install ttost, replace
clear all
set seed 2316
set obs 2000
gen x = rnormal()
gen y = 0.05*x + rnormal(0,1)         // 真实效应很小(0.05)

* 常规回归:p 不显著
reg y x
* 看到 p=0.18,错误写法:"政策无影响"

* TOST:设定等价界值 δ=0.1(即 |β|<0.1 视为无经济意义)
*   ttost 会做两个单侧检验:
*     H0a: β >= 0.1    vs H1a: β < 0.1
*     H0b: β <= -0.1   vs H1b: β > -0.1
*   两个都拒绝 → β 在 [-0.1, 0.1] 内 → 等价于0
* ttost coef=x, 0.1     // 或用回归后的 e() 直接做

* 关键:等价界值 0.1 必须在事前由经济意义定,
*      不能跑完 TOST 发现不通过,再换 δ=0.2 凑通过。
* 诚实写法:
*   "The 95% CI for β is [-0.03, 0.13], which lies
*    within our pre-specified equivalence bounds of
*    ±0.10; we therefore conclude the policy has at
*    most a negligible effect."

09 F 类 · 红线条目:留一系数排序删样本

⛔ 学术不端高风险:几乎无合法用途,切勿用于正式研究

下面这段手法,原样收录仅为让你认识它、在审稿或复现时能识破它。它的逻辑是:用 rangestat每一个观测做"剔除该观测后的回归",得到每个观测对应的留一法系数 b_x;然后按这个系数排序,系统性删除让系数不显著的那批观测——删 20 个跑一次回归看是否显著,不显著再删 20 个,直到核心变量显著为止。这是按回归结果反选样本,是最典型的样本操纵 / data dredging。用户的自我告诫:不到万不得已不要用。本页收录它,是为了防御——你必须能在别人的论文或自己的复现代码里认出这种操作。

F1留一系数排序,系统性删除观测直到显著

是什么:见上方 danger 说明。机制:留一系数 b_x 大的观测"把系数往显著方向拉",b_x 小的观测"把系数往零拉";按 b_x 排序删尾部,等价于人为挑选一组最有利的样本。合法性判别:红线条目。与 A6 影响诊断的本质区别在于:A6 是"发现已知是错误的观测并有依据删除",F1 是"不知道观测对不对,只因为它对我的结论不利就删"。审稿人如何识破:① 样本量与正文/数据附录对不上;② 复现失败(原始数据跑不出正文系数);③ robustness 表互相矛盾(全样本不显著、删完才显著);④ specification curve 审计会暴露"删除模式与系数单调对齐"。诚实替代:用 Cook's D/DFBETA 识别有明确记录理由的错误观测并说明删除依据;样本定义分析前确定并预注册;主结果报全样本,稳健性报有外部理由的子样本,而不是按系数排序删出来的子样本。

⛔ 以下代码为红线手法,原样收录仅供识别与复现审计,禁止用于你的研究
stata · F1_留一系数排序删样本(红线·仅识别用).do
*=================================================================
* F1 【红线手法 · 严禁用于正式研究】
* 留一法回归 + 按系数排序删样本,直到核心变量显著
* 收录目的:让你认识它、在审稿/复现时能识破它
*=================================================================
ssc install rangestat
gen _i = 1
gen _t = 1
* 对每个观测做"剔除该观测后"的回归,得到留一法系数 b_x
* (by(_i) 分组、i(_t 0 0) 在单点上做窗口;excludeself 排除自身)
rangestat (reg) y x controls, by(_i) i(_t 0 0) excludeself

* --- 若要把系数"调显著为负":按系数升序排列,删系数最小(最拖后腿)的那批 ---
gsort b_x
drop if _n<=20          // 一次删20个;不显著就继续删,直到显著
save data1.dta, replace

* --- 若要把系数"调显著为正":按系数降序排列 ---
gsort -b_x
drop if _n<=120
save data2.dta, replace

* 识别特征(审稿人视角):
*   - 删的数量(20/120)与"经济理由"毫无关系,纯由显著性决定
*   - 全样本回归不显著,删完才显著;删除模式单调对齐系数
*   - 复现代码里会出现 gsort b_x + drop if _n<=N 这种语句
* 诚实替代:Cook's D/DFBETA 只删"已确认录入错误"的观测,
*           并在附录列出删除清单与理由;样本定义事前预注册。

10 常见错误清单(自我审计用)

下列错误在投稿与复现中反复出现,建议逐条对照自查:

⚠ 14 条高频错误

错误 1:从 1%、2%、5% 缩尾里挑一个 p<0.05 的写正文、其余删稿——多档必须并列。
错误 2:加了一个控制变量后 N 从 68138 变 75000,正文不说明(A3/B1)。
错误 3:把 OLS、robust、聚个体、聚行业、双向聚类全跑一遍,只报最显著那一列(D1)。
错误 4:发现不加权不显著、加权后显著,就只报加权版,且权重来源只字不提(D2 红线)。
错误 5:逐期试 L1/L2/L3/L4,哪个滞后显著报哪个,无理论解释(E1)。
错误 6:分别跑国企/民企两个子样本,一组带星一组不带,就写"组间异质性"——必须交互项 test(H2)。
错误 7:DID 事前趋势不通过,却把事件研究图只画政策后部分"显得平行"(G1)。
错误 8:用 stepwise 按 p 值选控制变量,把噪声变量也选进基准模型(E3 红线)。
错误 9(G2 新):pre-trend 联合检验 p=0.21 就写"平行趋势成立"——忽略 Roth (2022) 证明的 pre-trend 检验功效常常只有 30–50%。
错误 10(G6 新):pre-trend 不通过后,事后把窗口从 ±5 改成 ±2、把漂移队列从样本里删掉"凑通过"。
错误 11(H1 新):把政策后才形成的中间变量(如生产率、创新)当作控制放进 X→Y 主回归,构成坏控制。
错误 12(H3 新):跑了 15 个因变量/子样本,只报 5 个带星的,从不做 Bonferroni 或 BH-FDR 校正。
错误 13(H5/H6 新):样本量小、SE 大、点估计不显著,就写"政策无影响"——既不报告事后功效,也不做 TOST。
错误 14(G5 新):交叠 DID 只跑 TWFE 事件研究图,不做 csdid/SA 等新估计量的干净 pre-trend 诊断。

✓ 一句话自检

对每一个你准备写进正文的规格,问一句:"如果它不显著,我还会这么做、并把它写进附录吗?"答"是"才是合法的稳健性;答"否",就是 p-hacking。

11 论文案例:p-hacking 与透明度经典文献

下列文献是"显著性操作"研究的源头与标尺,建议按顺序读:

Empirical Top-Field
Star Wars: The Empirics Strike Back
Brodeur, Lé, Sangnier & Zylberberg · American Economic Journal: Applied Economics, 2016, 8(1): 1–32
收集顶刊发表的数十万检验统计量,发现 p 值在 0.05 临界值附近显著"堆积"——这正是研究者在众多规格中只挑显著者留下的宏观指纹。(注意:该文发表于 AEJ: Applied,并非 AER;网络上常被误记为 AER。)
Empirical Top-Field
Unpacking P-Hacking and Publication Bias
Brodeur, Carrell, Figlio & Lusher · American Economic Review, 2023, 113(11): 2974–3002
利用期刊投稿(含被拒稿)数据发现:p 值堆积在初次投稿就已存在,说明发表后分布不能全归因于审稿人;边际显著结果更易被桌拒,审稿人推荐反而与显著性正相关。
Methodology
P-Curve: A Key to the File-Drawer
Simonsohn, Nelson & Simmons · Journal of Experimental Psychology: General, 2014, 143(2): 534–547
提出 p-curve:一组显著 p 值的分布形状可用于判断证据是否真实存在——真效应应右偏(更多 p≈.01),被 p-hack 出来的结果则接近均匀甚至左偏。姊妹篇 Simonsohn et al. (2015, Perspectives on Psychological Science) 用 p-curve 校正效应量。
Methodology
False-Positive Psychology: Undisclosed Flexibility in Data Collection and Analysis Allow Presenting Anything as Significant
Simmons, Nelson & Simmons · Psychological Science, 2011, 22(11): 1359–1366
用仿真证明:只要允许在"是否加第二个因变量、是否补样本、用哪种控制、何时停手"等少数自由度上自由选择,5% 的假阳性率可膨胀到 60% 以上。这就是"21 word solution"。
Methodology
Transparency, Reproducibility, and the Credibility of Economics Research
Christensen & Miguel · Journal of Economic Literature, 2018, 56(3): 1035–1080
系统综述经济学可复发性危机,讨论预注册、代码/数据公开、复制出版等制度回应,并按研究设计(RCT/RDD/DID/IV)讨论 p-hacking 程度差异。
Methodology
The Garden of Forking Paths: Why Multiple Choices in Data Analysis Can Contribute to Overconfidence
Gelman & Loken · American Scientist, 2013/2014 (working paper 2013)
即使没有恶意,研究中无数"看似都合理"的自由度叠加起来也会让假阳性率超标称水平——这就是花园分叉路径。本页所有"合法性判别"的哲学源头。
ℹ 姊妹页阅读建议

本页回答"每一次操作合法与否";姊妹页 12 显著性诊断实务回答"结果不显著时如何系统找病因"。两页配合使用:先用诊断实务定位根因,再回本页核对你准备采取的修正站在花园的哪一边。