ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Stata面板回归固定效应共线性报错:reghdfe命令从原理到实操全解析

Stata面板回归固定效应共线性报错:reghdfe命令从原理到实操全解析 刚接触Stata做面板数据回归的朋友大概率都撞上过这样一个报错variable industry_2 omitted because of collinearity明明数据没问题、代码也照着书敲了一跑固定效应模型就蹦出来一个“omitted”搞得人一头雾水。更常见的是你想同时控制行业和地区两个维度的差异直接在命令里噼里啪啦写上一堆i.industry i.province结果要么跑得奇慢无比要么结果表里全是点号根本没法看。这篇东西就是写给正在被这些问题折磨的人。我会从原理到实操把reghdfe这个命令讲透——它到底是干嘛的、为什么能解决多重固定效应和共线性问题、实际跑数据的时候有哪些细节会坑到你。文章里用到的示例和数据逻辑均基于常见实证场景看完你就能直接拿自己的数据上手。1. 先搞明白为什么“多重固定效应”会撞出共线性1.1 固定效应到底在固定什么面板数据里最常用的模型大概是这样的y_it α_i β*x_it ε_itα_i就是个体固定效应它把每个个体企业、城市、国家……不随时间变化的那些“天生特质”统统吸收掉。比如做企业层面的回归企业的注册地、所属行业、成立年限这些不太变的东西都会被固定效应吃掉这样你估计出来的β就不会被这些遗漏变量干扰。问题是真实研究里你往往不只想要个体固定效应。比如你想同时控制“行业差异”和“地区差异”那就得在模型里塞入行业虚拟变量和地区虚拟变量。Stata里最直接的办法是reg y x i.industry i.provincei.industry会把行业变量转成一组0/1虚拟变量i.province也是一样。理论上这没问题但实际一跑输出结果里就会出现一大片omitted。我相信每个跑过的人都见过这个。1.2 为什么会“omitted”共线性的本质是你放进模型里的某个自变量可以被其他自变量的线性组合完全表达出来。举个例子。假设你有10个行业、31个省份同时你还有一个“企业所在省份所属行业”的交互信息。如果你直接把行业虚拟变量、省份虚拟变量一起放进去某些行业只存在于某个省份里那么这个“行业×地区”的组合其实就只有一个企业在支撑对应的虚拟变量之间会产生近似完全共线。更极端的情况下如果某个行业在某个地区的所有企业都被你设了虚拟变量那么模型会把其中某一个自动省略以维持矩阵可逆。对于固定效应模型事情还会更复杂一些。面板数据里如果做“企业固定效应行业固定效应”双重控制你想想看企业固定效应已经把每个企业自己的“常数项”都估计出来了而行业固定效应又要再估计每个行业的“常数项”。一个企业的行业归属是不变的那么企业固定效应和行业固定效应之间就存在严重的线性依赖最小二乘法压根没法同时估计出这两组参数。这就是多重固定效应撞上共线性的本质。1.3 reg y x i.industry i.province 的替代方案有人可能会说那我就把行业虚拟变量也放进去让Stata自己omit掉太多共线的留下能识别的不就行了理论上是这样但实操中会遇到两个麻烦第一变量数量爆炸。31个省份就算30个虚拟变量20个行业就19个虚拟变量要是再想控制“行业×年份”的联合固定效应那就得生成几百个甚至上千个虚拟变量矩阵规模瞬间变大普通reg命令跑起来慢到你怀疑人生。第二即使能跑你也没法确认到底哪个虚拟变量被吞了、被吞掉的变量是否正是你关心的变量这会让结果解读变得非常不可靠——你自己心里没底审稿人一看也会追问。reghdfe解决的就是这件事。它换了一种数学算法不直接把所有虚拟变量放进矩阵而是通过“组内去均值”的方式把这些固定效应剥离掉再在干净的组内数据上做回归。结果等价于你手动生成了几百个虚拟变量再跑回归但速度和内存占用完全是两个量级。2. 装好reghdfe这一步比想象中更容易翻车2.1 安装命令与依赖关系在你兴冲冲地用reghdfe之前得先确保它已经躺在你的Stata里。安装倒不复杂ssc install ftool, replace ssc install reghdfe, replacereghdfe依赖ftool这个包来做一些内部矩阵运算所以先装ftool再装reghdfe是稳妥的顺序。某些老版本的Stata可能还需要gtools但如果你的Stata版本在15以上一般reghdfe的官方帮助文档里要求的依赖就是ftool。安装失败的常见原因有这么几个ssc install会去访问统计软件组件库的网络服务器有些网络环境下连接不稳定甚至直接被拒。这种时候别急着怀疑软件坏了换个网络环境重试或者过几分钟再试一次往往就好。Stata版本太老。reghdfe的一些功能要求Stata 14以上如果你还在用12甚至更老的版本安装可能会报错建议先升级Stata版本。本地Stata的ado路径权限不对。有些人安装的时候报“permission denied”这种情况通常是Stata安装在系统盘且没有以管理员身份运行时出现的。右键用管理员身份打开Stata再安装一次基本能解决。2.2 验证安装成功装完之后在Stata命令窗口输入which reghdfe如果返回类似这样的结果*! reghdfe 6.12.3 09may2023说明安装成功。这时候你可以先跑一个最小示例确认能正常工作webuse nlswork, clear xtset idcode year reghdfe ln_wage age hours, absorb(idcode year) vce(cluster idcode)nlswork是Stata自带的一个经典面板数据集美国女性劳动力追踪调查数据里面同时有跨个体、跨年份的维度跑一下这个例子你就能直观感受到reghdfe的输出长什么样。3. 数据准备别让“编码”毁掉你的固定效应3.1 行业变量、地区变量必须转为数值型因子很多人从Excel里导入数据时行业和地区是字符串比如制造业、北京。直接用i.industry时Stata虽然会自动处理字符串变量但一旦这个变量有缺失值或者有拼写不一致的情况比如“北京”和“北京市”并存就会产生莫名其妙的分类问题进而导致固定效应组别数量和你预想的不一致。稳妥的做法是手动生成数值型分类变量encode industry, gen(ind_code) encode province, gen(prov_code)encode会把字符串按字母或出现顺序映射成1、2、3……这样的正整数同时保留值标签。之后你用i.ind_code就非常清晰。如果行业和地区本身已经是数字编码比如国标行业分类代码、省份行政区划代码也要注意这些编码数字的大小本身没有含义必须用i.前缀告诉Stata它们是类别变量绝不能直接当作连续变量放进回归否则就是在篡改数据含义。3.2 处理“行业×年份”等联合固定效应时别在命令里硬写交互这是我自己踩过最深的坑。有一次我想控制“行业×年份”的联合固定效应也就是让每个行业在每一年都有自己的截距项直接在命令里写了reghdfe y x, absorb(i.ind_code i.year)跑是能跑但我很快发现这跟我想要的效果不一样。absorb(i.ind_code i.year)只是把行业固定效应和年份固定效应分别吸收掉并没有生成“行业×年份”的交互固定效应。真正的交互固定效应应该是每个行业在每一年都有一个单独的虚拟变量。有人会说那不是应该写成reghdfe y x, absorb(ind_code#year)对语法上是这么写但有一个先决条件你需要让Stata知道ind_code#year是一个完整的交互因子。实际操作中如果在absorb里直接写i.ind_code#i.yearStata会试图展开成一个巨大的稀疏矩阵——如果你的数据有100个行业、20年那就是2000个虚拟变量再叠加地区固定效应数据量稍微大一点内存就会爆掉。更好的做法是手动生成一个交互分类变量egen ind_year group(ind_code year) reghdfe y x, absorb(ind_year prov_code)egen group()会把“行业-年份”的每组组合编码成一个单独的变量然后reghdfe只需要吸收这一个变量就行了速度飞快而且逻辑上没有任何差别。这是我强烈推荐的做法——尽可能主动构造交互变量把复杂性挡在命令外面。3.3 缺省值、不平衡面板对固定效应的影响如果你的数据是不平衡面板有些个体只有部分年份的观测固定效应依然可以正常运行但要注意如果一个行业只出现了一年那么这个“行业×年份”的固定效应其实只有一个观测点在支撑估计出来的结果没什么意义却依然会消耗自由度。遇到这种情况建议在跑回归前先看一眼各组的样本量把那些出现频次过低的类别合并或者删除不然结果表里可能会冒出标准误大得离谱的系数。我这里提供一个快速查看组内样本量的方法bysort ind_year: gen N _N tab N看分布情况如果有很多N1的组那就要检查一下是不是行业编码过于细化、或者数据覆盖年份太少导致的。4. reghdfe实操把行业、地区、年份固定效应一次搞定4.1 基础命令格式先看最基础的多重固定效应写法reghdfe y x1 x2, absorb(ind_code prov_code year) vce(cluster idcode)这行的含义是在控制行业、省份、年份三类固定效应的同时估计x1和x2对y的系数并在个体层面idcode做聚类稳健标准误。absorb()括号里放的就是你想“吸收”掉的固定效应变量。它可以放很多个reghdfe会统一处理掉这些变量带来的虚拟变量问题然后你看到的回归表里只剩核心解释变量和常数项干净利落。vce(cluster idcode)的意思是基于个体层面的聚类稳健标准误。面板数据里同一个体不同年份的扰动项往往存在序列相关不聚类的话标准误会低估导致t值虚高——这是实证分析里的大忌。新手上路第一件事就是要记住面板数据回归必须聚类不聚类的结果不要报。4.2 结果的正确解读方式reghdfe跑完后输出表格分成上下两块。上部分是核心解释变量的系数、标准误、t值、P值、置信区间下部分重要信息是absorbed的行如下所示Absorbed degrees of freedom: ----------------------------------------------------- Absorbed FE | Num. Coefs. Categories - Redundant | --------------------------------------------------------| ind_code | 30 30 0 | prov_code | 30 30 0 | year | 14 14 0 | -----------------------------------------------------这行直接告诉你每个固定效应贡献了多少个虚拟变量以及其中有多少个因为共线性被判定为冗余。如果你发现某个固定效应的Redundant数量很多说明这部分虚拟变量和模型里的其他变量存在严重的多重共线性需要检查数据逻辑。回归结果里还会有R-squared和Adjusted R-squared但注意reghdfe默认报告的是组内R²within R²也就是剥离掉固定效应后纯粹由核心解释变量解释的变异比例。这个值通常比较小并不代表模型整体不好它只是衡量你要解释的那部分效应。如果你看到报告的R²只有0.1别着急先确认一下是within R²还是overall R²。4.3 多维固定效应可以任意组合reghdfe最强大的地方是你可以在absorb()里任意组合多个维度语法很灵活* 个体 年份 reghdfe y x, absorb(idcode year) vce(cluster idcode) * 行业 地区 年份 reghdfe y x, absorb(ind_code prov_code year) vce(cluster firm_id) * 行业×年份联合固定效应 地区固定效应 egen ind_year group(ind_code year) reghdfe y x, absorb(ind_year prov_code) vce(cluster firm_id)它甚至支持两层以上的交互固定效应比如你想控制“行业×地区×年份”就同样用egen构造三重组合即可。不过要提醒一句固定效应维度不是越多越好。固定效应吸收掉的自由度如果太多核心解释变量剩下的变异就很少估计精度会大幅下降。有些研究里行业、地区、年份三维固定效应加进去以后核心变量系数都不显著了——这并不一定是真的没效应很可能只是“被吸干了”。这也是为什么经验丰富的研究者会在稳健性检验里报告“只控制行业、只控制地区、行业地区同时控制”多档结果让读者看清楚结论是否依赖特定的固定效应组合。5. 共线性与“omitted”的排查技巧5.1 先用reg看基础共线性再用reghdfe做最终回归在正式跑reghdfe之前我建议新手先跑一个最朴素的回归reg y x1 x2 i.ind_code i.prov_code这个命令可能跑得很慢但它能快速暴露两个信息第一哪些变量被omitted了第二系数符号和大小是否符合常识。如果这里就有大量omitted说明变量之间的共线性非常严重你需要在数据层面解决而不是指望reghdfe帮你掩盖问题。reghdfe在absorb()里虽然能处理大量的虚拟变量但核心解释变量之间如果存在完全共线比如把x和2*x同时放进模型它同样会omit。遇到这种情况先从自变量本身入手排查。5.2 如何准确地找出共线变量跑完reghdfe后如果结果里有变量显示omitted你可以用以下方法快速定位共线关系reghdfe y x1 x2, absorb(ind_code year) vce(cluster idcode) estat vce或者用更直接的* 查看回归后哪些变量被omit reghdfe y x1 x2, absorb(ind_code year) vce(cluster idcode) matrix list e(b)e(b)里被省略掉的变量系数会显示为0名称也会被加锁。你在结果列表里看到0 (omitted)那就去数据里看看这个变量和哪个固定效应类别完全重合。更细致的排查可以通过_rmcoll命令来完成。_rmcoll是Stata内部用来检测共线性的命令它会返回一个处理过共线性后的变量列表你可以用它来确认到底哪里出了冗余_rmcoll x1 x2 i.ind_code i.year, expandexpand选项会把处理后的完整变量列表显示出来被删除的变量会标注(omitted)。通过这种方法你能精准地看到是哪两个虚拟变量之间存在完全共线。5.3 处理“虚拟变量陷阱”所谓“虚拟变量陷阱”就是你又想控制N个类别又想保留常数项结果模型无法同时识别。比如31个省份本来只需要30个虚拟变量你却在模型里把31个都放进去了就会导致完全共线。reghdfe在absorb()里会自动处理这个问题它会自动选择冗余的变量并剔除不会报错。这是它比手动生成虚拟变量省心的地方。但如果你把同一个维度既放进absorb()又放进解释变量里就会出问题。比如reghdfe y x i.year, absorb(ind_code year)i.year同时出现在解释变量和吸收项里模型会出现严重的共线性。reghdfe一般会omit掉i.year的某个虚拟变量但结果解读就会变得混乱。正确的做法是年份固定效应要么放在absorb()里要么显式作为解释变量二选一不要重复。6. 新手最容易踩的6个坑避坑清单6.1 全部避坑点速查表我把自己实操中遇到过的、以及帮别人改代码时常见的坑整理成了下面这个表格你可以直接截图保存。坑表现解法行业、地区变量是字符串固定效应组数不对、omitted诡异先encode成数值型在absorb()里写i.industry i.year跑得慢、交互固定效应没实现用egen group()手动构造交互变量忘了聚类标准误标准误偏小、t值虚高vce(cluster id)同一个维度既放absorb()又放解释变量重复共线、结果没法解释二选一不要在两边重复固定效应维度过多核心变量被“吸干”、系数不显著分档报告不做极端设定面板个体id编码重复或不唯一xtset报错、聚类无效用duplicates检查数据唯一性6.2 关于“重复id”这个隐蔽的坑第六条很多人会忽略。vce(cluster idcode)要求idcode能够唯一标识一个个体。如果你的数据是从多个表格合并来的idcode很可能在不同年份里重复使用表面上看着没问题但实际上同一个idcode对应了不同企业聚类标准误就被破坏了。处理办法是在合并后马上用duplicates检查isid idcode yearisid会检查idcode year的组合是否唯一。如果报错就说明数据里存在重复观测需要回看数据源的处理逻辑。这个步骤应该放在数据清洗的最前面而不是等跑完回归再回头排查不然返工成本极高。6.3 为什么固定效应模型里不要轻易“加常数项解释”还有一个新手很容易混淆的点reghdfe y x, absorb(ind_code year)跑完后如果你在结果里看到_cons常数项不要直接解读为“总体截距”。因为固定效应模型里的常数项只是一个参照组基础上的截距它本身没有太多经济含义。真正有含义的是核心解释变量的系数。很多人把_cons的显著性拿来讨论这其实是没必要的。7. 从reghdfe到更复杂的估计一个自然的延伸reghdfe能帮你解决多重固定效应问题但它本身是一个线性最小二乘估计器。如果你后续遇到了工具变量、面板Logit、高维固定效应的非线性模型那还需要其他配套命令工具变量法多重固定效应ivreghdfe它是在reghdfe基础上扩展的两阶段最小二乘版本用法很相似。高维固定效应的Logitlogit配合因子变量做多维固定效应经常会很慢可以考虑bife等命令。计数模型比如专利数ppmlhdfe可以处理多维固定效应的泊松回归。这些命令的底层思想都是“组内变换剥离固定效应”所以你会了reghdfe学其他的迁移成本就很小。这也是为什么我强烈建议新手把reghdfe作为固定效应模型的入门标配而不是长期停留在xtreg或者手动加虚拟变量的阶段。写到这里我想到之前帮一位师弟调代码的经历。他跑了一下午总是报omitted然后就把行业变量挨个删除试错改得一团糟。我过去看了一眼问题就出在他把行业和地区变量都用字符串导入了i.industry一共生成了几百个虚拟变量其中半数以上都是空的类别。解决方式就一行命令encode之后再跑。所以很多时候你遇到的不是模型问题而是数据编码和命令使用习惯的问题。如果你现在也在被固定效应的共线性报错折磨不妨按这个顺序自查先看数据结构再看命令写法最后才怀疑模型设定。多数坑都出在前两步。
返回列表