ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Stata 17实证模型代码全流程:从数据导入到面板固定效应与表格输出

Stata 17实证模型代码全流程:从数据导入到面板固定效应与表格输出

简介:这份资源面向使用Stata进行计量经济分析的研究生、科研人员与数据分析从业者,围绕Stata17的版本选型与常用模型代码展开。内容梳理了MP、SE、BE三个版本的特点与适用场景,其中MP为最高配版,适合大型数据集与多核处理器;同时对比Stata17相对Stata16的29项功能更新,涉及DID与DDD模型、面板数据多元logit模型,以及Python与Stata之间的数据交换。资源包共3个文件,以inscode工程配置、html页面与gitignore忽略规则为主,压缩包约7KB,体量轻便,便于快速导入与查阅。代码部分覆盖OLS模型、Heckman两阶段模型、PSM+DID模型等常用实现,并附面板熵值法计算代码与相关研究文献参考,可帮助读者直接对照复现、理解模型设定与结果解读。目前已有127人学习下载,适合需要快速上手Stata17新特性、补齐计量模型代码模板的初中级用户参考。

1. 计量圈的老伙计:Stata 17 与配套模型代码到底能解决什么

如果你做实证研究,大概率绕不开 Stata。它不像 R 那样需要你精通编程范式,也不像 SPSS 那样点几下就到底、想改个似然函数都没门。Stata 17 卡在一个很舒服的位置:命令行驱动、矩阵运算够用、面板和生存分析开箱即用,而且 do-file 天然可复现。但真正让人头疼的从来不是软件本身,而是「模型代码」——同样一个双重差分,别人跑出来显著,你跑出来系数符号都反了,问题往往出在数据清洗、固定效应设定和聚类层级上。这份资源把 Stata 17 和一套可直接运行的模型代码打包在一起,覆盖从数据导入、变量构造到回归输出、稳健性检验的完整链路。适合正在写论文的硕博生、需要快速复现文献结果的从业者,以及被「代码跑不通但不知道错在哪」折磨过的实证新手。它不教你计量经济学原理,但能让你把原理落成一行行能跑的命令。

2. 环境准备与数据导入:别让编码和路径毁掉第一行代码

2.1 Stata 17 的安装与版本差异确认

拿到资源后第一件事不是急着跑代码,而是确认版本。Stata 17 相比 16 最大的变化在于frames框架、table命令的增强,以及 Python 和 Jupyter 的集成。如果你的代码里出现了frame相关命令,在 16 上会直接报command frame is unrecognized。常见做法是先在命令窗口敲:

display c(version) display c(stata_version)

第一行返回 Stata 的版本号,第二行返回具体修订版本。如果显示的是 17.x,说明环境没问题。安装时注意两点:一是不要装在带中文或空格的路径下,Stata 对路径中的非 ASCII 字符处理一直不太稳定,cd到中文目录后use报file not found是血泪经验;二是确认ado目录的读写权限,很多第三方命令需要写入plus文件夹,权限不足会报unable to write。

2.2 数据导入的三种姿势与编码坑

资源里的数据通常是.dta格式,但实际工作中你拿到的可能是 CSV 或 Excel。Stata 17 导入 CSV 的标准命令是import delimited,但中文数据最容易翻车的地方是编码。Windows 下 Excel 导出的 CSV 默认是 GBK,而 Stata 17 默认按 UTF-8 读取,结果就是变量名和字符串变量全变乱码。

* 方式一:直接导入 dta,最省事 use "data/panel_data.dta", clear * 方式二:导入 CSV 并指定编码 import delimited "data/raw_data.csv", clear encoding("GB18030") * 方式三:导入 Excel 指定 sheet 和单元格范围 import excel "data/raw_data.xlsx", sheet("Sheet1") cellrange(A1:H1000) firstrow clear

encoding("GB18030")是关键参数,它兼容 GBK 和 GB2312,比单纯写gbk更稳。firstrow告诉 Stata 第一行是变量名,不加的话你会得到v1到vN这种默认名。导入后立刻用describe和codebook扫一遍,重点看字符串变量有没有截断、数值变量有没有被识别成字符串。如果数值变量被读成字符串,用destring转换:

destring gdp_per_capita, replace force

force会把无法转换的值设为缺失,不加则遇到非数值字符直接报错停止。我一般会先不加force跑一遍,看看报错位置的数据长什么样,确认是脏数据后再加。

2.3 路径管理与 do-file 的工程化习惯

资源里的代码通常用相对路径,但很多人直接双击 do-file 运行,工作目录不对就全线崩溃。正确做法是在 do-file 开头显式设定:

* 设定项目根目录,后续所有路径基于此 global root "D:/project/stata_model" cd "$root" * 用 global 管理常用路径 global data "$root/data" global output "$root/output" global log "$root/log" * 开启日志,记录所有命令和输出 log using "$log/run_$(c(current_date)).log", replace

global定义的宏在后续代码中用$data引用,改路径只需改一处。日志文件用c(current_date)自动加日期,避免覆盖。do-file 结尾记得log close,否则日志文件会一直被占用。这套习惯看起来琐碎,但当你需要跑几十个模型、回头查某一步输出时,没有日志就是黑匣子。

3. 核心模型代码拆解:从 OLS 到面板固定效应的参数逻辑

3.1 基准回归的代码结构与选项含义

资源里的模型代码一般从基准 OLS 开始,逐步加到固定效应和聚类标准误。先看一段典型的基准回归:

* 基准 OLS:y 对 x1 x2 回归,robust 标准误 reg y x1 x2 x3, robust * 存储估计结果,供后续输出表格 estimates store model1 * 加入平方项和交互项 gen x1_sq = x1^2 gen x1_x2 = x1*x2 reg y x1 x1_sq x2 x1_x2 x3, robust estimates store model2

robust选项给出异方差稳健标准误,这是实证论文的默认要求。不加robust得到的标准误在异方差存在时是有偏的,t 值虚高,容易把不显著的结果跑成显著。estimates store把结果暂存,后面用esttab或outreg2输出成表格时直接调用。平方项和交互项一定要用gen显式构造,不要在回归里写c.x1#c.x1,虽然语法支持,但后续做边际效应时显式变量更直观。

3.2 面板固定效应:xtreg 与 reghdfe 的选择

面板数据是 Stata 的强项,但xtreg和reghdfe的取舍经常让人纠结。xtreg是官方命令,支持fe、re、be三种估计,但只能处理一个固定效应维度。reghdfe是第三方命令,能同时吸收多个高维固定效应,速度快,但需要先安装。

* 设定面板结构 xtset id year * 个体固定效应 xtreg y x1 x2 x3, fe robust estimates store fe_model * 双向固定效应:个体 + 时间 xtreg y x1 x2 x3 i.year, fe robust estimates store twoway_model * reghdfe 多维度固定效应 reghdfe y x1 x2 x3, absorb(id year) vce(robust) estimates store hdfe_model

xtset id year是面板分析的前提,id是个体标识,year是时间变量。fe估计会消去个体不随时间变化的特征,代价是无法估计性别、种族这类时不变变量的系数。i.year生成年度虚拟变量,吸收时间固定效应。reghdfe的absorb(id year)等价于双向固定效应,但计算效率高得多,尤其是个体数上万时。vce(robust)对应xtreg的robust,聚类标准误则用vce(cluster id)。

3.3 聚类标准误的层级选择与自由度调整

聚类层级选错是实证中最隐蔽的坑。常见做法是聚类到个体层面,但如果处理变量是在省份层面分配的,聚类到个体就低估了标准误。资源里的代码一般会提供多种聚类方案供对比:

* 聚类到个体 xtreg y x1 x2 x3, fe vce(cluster id) * 聚类到省份 xtreg y x1 x2 x3, fe vce(cluster province) * 双向聚类(需要 reghdfe 或 ivreg2) reghdfe y x1 x2 x3, absorb(id year) vce(cluster id province)

聚类层级越高,标准误越大,显著性越保守。如果处理变量在省份层面,聚类到省份是底线。双向聚类同时考虑个体和省份内的相关性,但要求两个维度的聚类数都足够多,否则自由度调整后标准误会爆炸。Stata 17 的xtreg在聚类数少于 30 时会给出警告,这时候要么用boottest做 wild bootstrap,要么老实报告聚类数不足的局限。

3.4 工具变量与 GMM 的代码模板

内生性是逃不掉的问题,资源里通常包含ivregress和xtabond2的模板:

* 2SLS:x1 内生,z1 z2 为工具变量 ivregress 2sls y x2 x3 (x1 = z1 z2), robust estimates store iv_model * 面板 GMM:动态面板,滞后项作工具 xtabond2 y L.y x1 x2, gmm(L.y, lag(2 4)) iv(x1 x2) robust

ivregress 2sls的括号内是内生变量和工具变量,括号外是外生变量。工具变量有效性需要看第一阶段 F 值,经验规则是大于 10。xtabond2的gmm()指定内生变量的滞后项作为工具,lag(2 4)表示用第 2 到第 4 期滞后。iv()指定外生变量。GMM 的关键是自相关检验,xtabond2会输出 AR(1) 和 AR(2) 的 p 值,AR(2) 不显著才说明工具变量设定合理。

4. 避坑与排查:那些让结果差之毫厘的细节

4.1 现象:固定效应回归系数与文献相反

原因通常有两个:一是固定效应的吸收方式不同,xtreg, fe和areg在缺失值处理上有细微差别,导致样本量不一致;二是变量构造时没有对齐面板结构,比如价格指数没有用基期调整,或者名义变量没有平减。解决方法是先用xtset确认面板平衡性,用xtdescribe看每个个体的时间跨度,再用misstable summarize检查缺失模式。如果缺失集中在某些年份,固定效应估计的样本就是非随机的。

4.2 现象:聚类标准误比稳健标准误还小

这听起来反直觉,但确实会发生。原因是聚类数太少时,Stata 的自由度调整公式会给出偏小的标准误。xtreg在聚类数 G 小于 30 时用的是 t(G-1) 分布,但如果 G 只有 5 到 10,这个近似很差。解决方法是改用 wild cluster bootstrap,或者报告reghdfe的cluster结果并注明聚类数。另一个可能是聚类变量有大量缺失,实际参与聚类的观测远少于预期。

4.3 现象:do-file 跑一半报错,但单独跑那行没问题

这是典型的宏污染或数据状态残留。do-file 是顺序执行的,前面的gen或replace改变了数据,后面的命令依赖的是改变后的数据。单独跑那行时数据是初始状态,所以没问题。排查方法是在报错行之前加describe和count,确认数据状态。更彻底的做法是每个模型块之前重新use一次原始数据,或者用preserve/restore包裹临时操作。

4.4 现象:outreg2 或 esttab 输出的表格缺变量

通常是estimates store的名字重复了,后面的覆盖了前面的。Stata 允许同名存储,但不会警告。解决方法是给每个模型起唯一的名字,比如model1_ols、model2_fe,输出前用estimates dir列出所有已存储的估计。另一个可能是某些模型因为样本量不足没有估计出来,estimates store存了个空壳,输出时自然缺行。

4.5 现象:中文变量标签在图中显示为方框

Stata 17 的图形引擎对中文字体支持取决于系统字体配置。Windows 下默认的Arial不含中文字形,需要显式指定中文字体:

graph set window fontface "Microsoft YaHei"

这行命令把图形窗口的默认字体设为微软雅黑。如果导出 PDF 或 PNG 仍有问题,在graph export时加fontface("Microsoft YaHei")。Mac 下对应的是"PingFang SC"或"STHeiti"。这个设置不改变数据,只影响显示,但论文里的图如果全是方框,审稿人第一印象就差了。

5. 进阶技巧:用 putdocx 和循环批量产出回归表格

5.1 用循环跑多组子样本并自动命名

实证里经常需要分样本回归,比如按地区、按年份、按企业规模分组跑同一个模型。手动改代码不仅慢,还容易漏。用levelsof加foreach可以自动化:

* 获取 region 的所有取值 levelsof region, local(regions) * 循环每个地区跑回归并存储 foreach r of local regions { reg y x1 x2 x3 if region == `r', robust estimates store model_`r' }

levelsof把region的去重值存入局部宏regions,foreach遍历每个值。if region ==r'中的反引号是 Stata 的局部宏引用语法,r在循环中依次取每个地区编码。存储的名字model_r'会自动带上地区后缀,后续输出时用estimates dir能看到全部。注意levelsof对字符串变量也适用,但值里不能有空格,否则需要加clean选项处理。

5.2 用 putdocx 直接生成 Word 表格

Stata 17 内置的putdocx比outreg2更灵活,能直接生成带格式的 Word 文档:

* 创建 Word 文档 putdocx begin * 添加标题段落 putdocx paragraph, style("Heading 1") putdocx text "表 1:基准回归结果" * 插入回归表格 putdocx table results = etable, model1 model2 model3 * 保存 putdocx save "$output/regression_tables.docx", replace

putdocx table的etable语法直接调用之前estimates store的结果,model1 model2 model3按顺序排列。生成的表格自带系数、标准误和显著性星号。如果需要自定义格式,可以在etable后加stats()选项控制报告哪些统计量。putdocx save的replace选项覆盖同名文件,不加则报错。这套流程跑下来,从数据到成稿表格不超过 10 秒,比手动复制粘贴靠谱得多。

5.3 一个我踩过的坑:putdocx 的字体继承

putdocx默认继承 Stata 的图形字体设置,如果之前用graph set window fontface改过中文字体,Word 文档里的中文会正常显示。但如果没改过,导出的 Word 里中文可能变成乱码或方框。我现在的习惯是在putdocx begin之后立刻加一行:

putdocx paragraph, font("Microsoft YaHei", 10.5)

这行设置后续段落的默认字体。注意putdocx的字体设置是段落级的,表格内的字体需要单独用putdocx table的font()选项控制。从那以后我每次生成 Word 报告都强制走一遍字体检查,再也没出现过方框问题。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进