
简介这份资源面向使用Stata进行计量经济分析的研究生、科研人员与数据分析从业者围绕Stata17的版本选择与常用模型代码展开帮助读者在MP、SE、BE三个版本之间做出合理取舍并快速调用成熟的分析脚本。压缩包共3个文件以inscode脚本、html说明页与gitignore配置为主整体约7KB体量轻便便于直接导入项目或版本管理工具中使用。资源重点梳理了Stata17相较Stata16的29项功能更新涵盖DID与DDD模型、面板数据多元logit模型以及Python与Stata之间的数据交换能力同时给出OLS模型、Heckman两阶段模型、PSMDID模型等常用代码和面板熵值法计算代码并附相关研究文献参考。已有127人学习下载适合希望减少重复编码、对照文献复现实证结果的中高级用户参考。1. Stata 17 与模型代码版本差异到底会不会让你的回归结果翻车很多人第一次遇到 Stata 17 的代码问题不是语法不会写而是同一份 do 文件在旧版本能跑换到 17 就报错或者系数对不上。我见过最典型的一次某实验室用xtreg做面板固定效应旧版本跑出来组内 R² 是 0.43换到 Stata 17 后变成 0.41差得不多但审稿人一眼就看出来了。后来排查半天发现是 17 对缺失值的默认处理和vce选项的底层实现有调整。这不是玄学是版本迭代里真实存在的边界变化。Stata 17 在模型代码层面主要动了三块一是reghdfe、xtreg这类高频命令对高维固定效应的收敛容差更严二是margins和contrast在因子变量交互项上的标准误计算路径有微调三是bayes前缀和gsem的默认先验与迭代上限变了。这些改动对做应用微观计量的人影响最大因为大家往往直接抄旧代码不检查版本适配。这篇文章就是把我自己踩过的坑和能直接复用的代码框架讲清楚适合手里有 Stata 17 但不确定旧模型代码能不能直接迁移的从业者。2. Stata 17 模型代码的版本适配与最小可复现框架2.1 先确认你的 Stata 17 到底改了哪些默认行为不要一上来就改代码先花五分钟做版本行为对照。Stata 17 的version命令可以锁定语法版本但很多人不知道它只影响命令解析不影响数值计算路径。真正影响结果的是set里的几个底层参数。我一般会先跑一段诊断脚本把关键默认值打印出来和旧版本截图对比。* 版本行为诊断脚本 version 17 // 锁定语法版本为17避免旧命令被拒绝 set matsize 10000 // 17默认matSize上限提高但旧do文件可能显式设了更小值 set maxvar 32767 // 变量数上限17支持更大但旧代码可能卡在旧上限 display c(version): c(version) display c(maxmat): c(maxmat) display c(maxvar): c(maxvar) display c(MP): c(MP) display c(SE): c(SE) * 检查缺失值处理默认值 display c(missing): c(missing)这段代码的逻辑是先把语法版本锁死防止旧命令被 17 的新解析器拒绝然后打印矩阵和变量上限因为很多旧 do 文件在开头写了set matsize 800到 17 里虽然能跑但遇到高维固定效应时矩阵不够大就会静默截断。c(missing)在 17 里默认是.但如果你从更早版本迁移有些旧代码依赖c(missing)返回特定值来做条件判断这里必须显式检查。参数说明version 17只影响语法不影响数值set matsize建议设到 10000 以上做高维固定效应时甚至要 20000set maxvar在 17 里可以到 32767但内存不够时别硬撑。2.2 用 reghdfe 和 xtreg 跑通一个最小面板模型选reghdfe还是xtreg我的判断标准很简单固定效应维度超过两个或者需要吸收高维固定效应直接用reghdfe只有个体和时间两个维度且要做 Hausman 检验用xtreg更顺。Stata 17 里reghdfe的收敛容差默认从 1e-8 收紧到 1e-10这意味着旧代码里如果没设tolerance结果会有微小差异。下面是一个最小可复现的面板回归框架数据用 Stata 自带的nlswork。* 最小面板回归框架reghdfe vs xtreg webuse nlswork, clear xtset idcode year * 路径Areghdfe 吸收个体和年份固定效应 reghdfe ln_wage tenure hours, absorb(idcode year) vce(cluster idcode) tolerance(1e-10) estimates store reghdfe_model * 路径Bxtreg 个体固定效应 xtreg ln_wage tenure hours i.year, fe vce(cluster idcode) estimates store xtreg_model * 对比系数和标准误 estimates table reghdfe_model xtreg_model, star(0.05 0.01 0.001) stats(N r2_w r2_o)逻辑说明reghdfe的absorb(idcode year)一次性吸收两个高维固定效应tolerance(1e-10)是 Stata 17 下的推荐值不写的话默认值在 17 里也是 1e-10但显式写出来方便跨版本复现。xtreg的i.year把年份作为虚拟变量放进回归fe指定个体固定效应。两个模型在系数上应该几乎一致但标准误会有细微差别因为reghdfe的自由度调整和xtreg不同。参数说明vce(cluster idcode)是个体层面聚类稳健标准误做微观面板几乎必选tolerance越小收敛越慢但越精确1e-10 是 17 的默认旧版本迁移过来建议显式写estimates table里的r2_w是组内 R²r2_o是整体 R²对比时重点看组内。2.3 因子变量交互项在 margins 里的标准误变化Stata 17 对margins和contrast在因子变量交互项上的标准误计算做了调整尤其是涉及i.和c.混合的时候。旧代码里常见的写法是margins i.group, at(age(30 40 50))在 17 里如果模型用了reghdfemargins默认不再自动识别吸收掉的固定效应需要加predict(xb)或者改用margins, dydx()的显式形式。我一般会先跑一个交互项模型然后用margins和contrast各算一遍看差异。* 因子变量交互项与 margins 标准误对比 reg ln_wage c.tenure##i.collgrad hours, vce(cluster idcode) * 旧写法直接 margins margins i.collgrad, at(tenure(1 5 10)) estimates store margins_old * 17推荐写法显式指定预测类型 margins i.collgrad, at(tenure(1 5 10)) predict(xb) estimates store margins_new * 用 contrast 做交互项联合检验 contrast i.collgrad#c.tenure, effects逻辑说明c.tenure##i.collgrad是连续变量和因子变量的全交互margins在 17 里对xb的默认预测类型更严格不加predict(xb)时如果模型有聚类标准误标准误会偏大。contrast是 17 里替代testparm做交互项联合检验的推荐命令effects选项输出边际效应。参数说明at(tenure(1 5 10))指定连续变量的取值点做交互项时至少取三个点才能看出趋势predict(xb)是线性预测值做连续变量交互时用这个contrast的effects选项在 17 里比testparm更稳健尤其是聚类标准误下。3. 把旧 do 文件迁移到 Stata 17 的实操步骤3.1 迁移前的版本兼容性扫描不要直接跑旧 do 文件先做一次静态扫描。我一般会写一个脚本把旧 do 文件里所有可能受版本影响的命令列出来然后逐条对照 Stata 17 的帮助文档。重点看四类命令xtreg、reghdfe、margins、gsem。下面这个扫描脚本可以复用。* 旧do文件兼容性扫描 local old_do old_model.do file open fh using old_do, read local lineno 0 while 1 { file read fh line if r(eof) break local lineno * 检查高风险命令 foreach cmd in xtreg reghdfe margins gsem bayes { if strpos(line, cmd) 0 { display 行 lineno: 发现 cmd - line } } * 检查显式版本锁定 if strpos(line, version ) 0 { display 行 lineno: 版本锁定 - line } } file close fh逻辑说明逐行读取旧 do 文件遇到高风险命令就打印行号和内容。version锁定行也要看因为旧代码可能写了version 14在 17 里会强制用 14 的语法解析但数值计算还是 17 的这种混合状态最容易出问题。参数说明local old_do换成你的文件名foreach cmd列表按你实际用到的命令增删strpos返回位置大于 0 表示命中。3.2 逐命令替换与回归结果比对扫描完之后不要一次性全改按命令逐个替换并比对结果。我的做法是先跑旧版本结果存成estimates再跑 17 版本结果用estimates table并排看。下面以xtreg为例展示迁移前后的代码差异和比对方法。* 迁移前旧版本写法假设从Stata 15迁移 version 15 xtreg ln_wage tenure hours i.year, fe vce(cluster idcode) estimates store old_result * 迁移后Stata 17写法 version 17 xtreg ln_wage tenure hours i.year, fe vce(cluster idcode) iterate(100) estimates store new_result * 并排比对 estimates table old_result new_result, star(0.05 0.01 0.001) /// stats(N r2_w r2_o sigma_u sigma_e rho) b(%9.4f) se(%9.4f)逻辑说明旧版本xtreg的默认迭代上限是 5017 里提高到 100但如果你旧代码里显式写了iterate(50)迁移后要改成 100 或者删掉。sigma_u、sigma_e、rho是面板方差分解参数17 里对不平衡面板的rho计算有微调比对时重点看这三个。参数说明iterate(100)是 17 的默认显式写出来方便复现b(%9.4f)和se(%9.4f)控制系数和标准误的小数位比对时至少保留四位。3.3 用 do 文件版本控制做可复现归档迁移完成后必须做版本归档。我见过太多人改完就跑过两个月自己都忘了哪版对应哪个结果。Stata 17 里可以用datasignature和cf做数据与代码的联合校验再配合log做完整归档。下面是一个归档模板。* 可复现归档模板 log using model_v17_c(current_date).log, replace text * 数据签名 datasignature set, reset datasignature report * 代码版本记录 display do文件: model_v17.do display Stata版本: c(version) display 运行时间: c(current_date) c(current_time) * 跑模型 webuse nlswork, clear xtset idcode year xtreg ln_wage tenure hours i.year, fe vce(cluster idcode) estimates store final_model * 保存估计结果 estimates save final_model.ster, replace log close逻辑说明datasignature set, reset给当前数据集打签名datasignature report打印签名值别人拿到数据和 do 文件后可以校验是否一致。estimates save把估计结果存成.ster文件后续可以用estimates use直接加载不用重跑。参数说明log using的text选项生成纯文本日志方便版本控制c(current_date)和c(current_time)是 Stata 内置宏自动填当前日期时间.ster文件是 17 的二进制估计结果格式跨版本兼容性一般建议同版本内使用。4. Stata 17 模型代码的避坑与排查记录4.1 避坑一reghdfe 收敛失败但无报错现象reghdfe跑完显示converged但系数和旧版本差很多且e(converged)返回 0。原因Stata 17 里reghdfe的默认容差收紧后高维固定效应下迭代次数不够但命令不报错只把converged标志置 0。解决显式加tolerance(1e-10) iterate(1000)并在跑完后检查e(converged)如果是 0 就换acceleration(cg)或damping选项。reghdfe ln_wage tenure hours, absorb(idcode year) vce(cluster idcode) /// tolerance(1e-10) iterate(1000) acceleration(cg) display 收敛标志: e(converged)4.2 避坑二margins 在 reghdfe 后标准误异常大现象reghdfe后跑margins标准误比xtreg后大好几倍。原因reghdfe吸收固定效应后margins默认用predict(xb)但自由度调整基于吸收后的残差导致标准误膨胀。解决改用margins, dydx()并显式指定vce(unconditional)或者直接用xtreg跑对应模型再算 margins。* 方案A显式指定vce margins, dydx(tenure) at(collgrad(0 1)) vce(unconditional) * 方案B换xtreg xtreg ln_wage c.tenure##i.collgrad hours i.year, fe vce(cluster idcode) margins i.collgrad, at(tenure(1 5 10))4.3 避坑三gsem 默认先验变化导致贝叶斯结果漂移现象gsem加bayes前缀后后验均值与旧版本差超过 5%。原因Stata 17 把gsem的默认先验从normal(0, 100)改成normal(0, 10000)方差先验更平后验分布更宽。解决显式指定先验或者用prior()选项锁定旧先验。* 显式锁定旧先验 bayes, prior({ln_wage:tenure} normal(0, 100)) /// prior({ln_wage:hours} normal(0, 100)) /// prior({ln_wage:_cons} normal(0, 100)): /// gsem (ln_wage - tenure hours)4.4 避坑四旧 do 文件里的 set matsize 导致静默截断现象旧 do 文件开头写了set matsize 800在 17 里跑高维固定效应时矩阵不够大但 Stata 不报错只把部分固定效应丢掉。原因set matsize在 17 里虽然支持更大值但旧代码显式设的小值会覆盖默认。解决删掉旧set matsize行或者改成set matsize 20000并在跑模型前用display c(maxmat)确认。* 检查并修正矩阵上限 display 当前matSize: c(maxmat) set matsize 20000 display 修正后matSize: c(maxmat)4.5 避坑五estimates save 跨版本加载失败现象用 Stata 16 存的.ster文件在 17 里estimates use报错。原因.ster格式在 17 里有内部结构变化旧版本文件不保证向下兼容。解决不要跨版本存.ster改用estimates table导出文本或者用outreg2、esttab导出表格。* 跨版本安全导出 esttab using results.csv, replace se star(* 0.1 ** 0.05 *** 0.01) /// stats(N r2_w r2_o) b(%9.4f) se(%9.4f)5. 用 Stata 17 做模型代码版本管理的进阶习惯我现在的习惯是每个项目根目录下放一个stata_version.do里面只做三件事——锁定版本、打印环境、校验数据签名。这个文件不跑模型只做环境声明。然后每个模型单独一个 do 文件文件名带版本号比如model_panel_v17.do。跑完模型后用estimates save存.ster同时用esttab导出.csv两个都进版本控制。.ster用于同版本内快速加载.csv用于跨版本比对和审稿人查看。还有一个技巧Stata 17 的frames功能可以让你在同一个会话里同时持有多个数据集做迁移比对时特别有用。比如旧版本结果放在frame old新版本结果放在frame new然后用frame命令切换不用反复webuse和clear。下面是一个 frames 比对模板。* frames 多数据集比对模板 frame create old frame create new * 旧版本结果 frame old { webuse nlswork, clear xtset idcode year xtreg ln_wage tenure hours i.year, fe vce(cluster idcode) estimates store old_model } * 新版本结果 frame new { webuse nlswork, clear xtset idcode year xtreg ln_wage tenure hours i.year, fe vce(cluster idcode) iterate(100) estimates store new_model } * 跨frame比对 frame old: estimates table old_model, b(%9.4f) se(%9.4f) frame new: estimates table new_model, b(%9.4f) se(%9.4f)逻辑说明frame create创建独立的数据容器每个 frame 有自己的数据集和估计结果。frame old { ... }在大括号内跑旧版本代码frame new { ... }跑新版本。比对时用frame old: estimates table和frame new: estimates table分别输出不用来回切换。参数说明frame create的名字不能和现有变量重名大括号内的代码在对应 frame 里执行不影响其他 frameestimates store存的模型名在各自 frame 内独立不会冲突。最后说一个我自己的教训有一次赶论文旧 do 文件直接扔进 Stata 17 跑结果reghdfe的converged标志是 0但输出表格里没显示我直接用了结果。后来审稿人要求复现才发现系数差了 0.02。从那以后我每次跑完reghdfe都会加一行assert e(converged) 1不通过就停下来查。这个习惯帮我省了至少三次返工。希望帮到你。本文还有配套的精品资源点击获取