news 2026/10/5 6:09:23

分位数回归原理与Stata实操:从均值视角到全貌视角的异质性分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分位数回归原理与Stata实操:从均值视角到全貌视角的异质性分析

自己做实证研究这些年,有一类问题几乎每次都会被审稿人追问:“你只报告了均值回归,难道不同人群里自变量的影响没有差异吗?”刚开始我不太当回事,直到自己用OLS跑教育回报率,得到一个“平均效应约为8%”的漂亮结果,后来被人提醒“高收入人群和低收入人群的教育回报可能差出一倍”,才意识到均值回归有时候真的会骗人。也是从那时候开始,我认真学起了分位数回归,并且把主力工具从顺手就用的回归命令换成了Stata里的一套组合拳。

这篇文章就聊聊分位数回归到底在做什么,以及我平时在Stata里具体怎么操作、怎么读结果、怎么画图、遇到问题怎么排查。内容基本按照我自己从入门到熟练的实际路径来写,适合正在做实证分析、被“异质性分析”困扰的同学,也适合刚接触Stata、想在论文里引入更丰富结论的科研新手。你会看到完整的命令、输出解读和踩坑记录,照着做基本就能跑通。

1. 为什么你需要分位数回归:从“平均视角”到“全貌视角”

1.1 均值回归的真正盲区

普通最小二乘法(OLS)估计的是自变量对因变量条件均值的影响。这句话说起来很简单,但很多人没有意识到“均值”这两个字有多大的掩盖作用。假设教育年限对收入的影响在低收入群体里是3%,在高收入群体里是15%,OLS给出来的可能就是一个中间值,比如8.5%,你会觉得“教育对所有人都挺重要”,但实际上它对刚起步的年轻人可能没那么重要,而对已经爬到管理层的资深人士来说,决定意义却大得多。

OLS也不是完全看不到这种差异,最常用的替代方案是分组回归,比如按收入中位数把样本砍成两组分别跑。但这里有个问题:分组界限是你主观定的,按30%分和按50%分结果可能不一样;而且两组内部的个体差异依然存在,等于用一次粗切把连续的变化硬掰成了离散的两块。另一个常见思路是在模型里加交互项,比如education × high_income_group,但交互项只能处理你明确写出来的那一个分组变量,现实中影响机制的异质性往往不是单靠一两个虚拟变量能刻画的。

分位数回归补上的正是这块拼图。它不要求你做任何分组切分,而是直接在因变量的不同分位点(10%、25%、50%、75%、90%)上分别估计自变量的影响。这意味着你不需要事先定义“穷人”和“富人”,数据会把人口从低到高排好队,你只需要回答“在第10个百分位的人,教育回报是多少;在第90个百分位的人,教育回报又是多少”。每一个分位点的回归都用了全样本,所以估计效率比切子样本高得多,结果也更稳定。

1.2 分位数回归能回答什么问题

简单说,分位数回归回答的是“自变量的影响在整个结果分布中是否均匀”这个问题。如果一份政策评估报告只汇报“平均处理效应为X元”,而政策对象当中最需要帮助的那批人恰好处于分布的底层,那这个X可能完全无法反映政策对他们的真实效果。分位数回归让你看到的是从低分位到高分位一整条影响曲线,而不是一个孤零零的点。

我自己的经验里,这种“全貌视角”在几类场景下特别有价值。一是劳动经济学里的收入决定因素研究,收入分布通常右偏,高收入段和低收入段的行为模式差异很大;二是健康经济学里的医疗费用分析,大部分人的医疗支出很低,少数人账单高得离谱,均值回归会被极端值拖着走;三是教育经济学里的学业表现研究,老师、班级规模等因素对尖子生和及格线附近学生的影响机制完全不同。这些场景的共同特点是:因变量分布不均匀,且关心的人群本来就不该被“平均化”。

1.3 分位数回归跟分组回归怎么取舍

有人会问,既然分位数回归这么好,分组回归是不是就该淘汰了?也不是。分组回归的优势在于结果直观,报告起来简单,而且当分组变量本身就有经济学含义的时候(比如性别、地区、城乡),分组天然有意义。分位数回归适合回答“连续分布上的不同位置”,分组回归适合回答“离散类别之间的差异”,两者完全可以互补。

实操中我经常这样组合使用:先做全样本OLS拿到基准结果,再做分位数回归看系数的连续变化轨迹,最后挑选一两个有制度含义的分组变量做交互或子样本回归,用分组结果给分位数回归的发现做交叉验证。审稿人看到这种思路,基本不会再说你只看平均值了。

2. 分位数回归的核心原理与参数解读

2.1 Check Function:分位数回归在优化什么

要说清楚分位数回归的原理,绕不开它的损失函数。OLS想找一组系数,让残差平方和最小,这个目标函数对极端值非常敏感,一个异常值就能把整条回归线拉偏。分位数回归换了一个思路:它想找一组系数,让“加权绝对残差”最小,权重由你选取的分位点τ决定。

具体来说,对于分位点τ(比如0.5),损失函数是: ρ_τ(u) = u × (τ - I(u < 0)) 其中u是残差,I是指示函数。当残差为正(实际值高于预测值),损失是 τ×u;当残差为负,损失是 (τ-1)×u。你让这个加权绝对值之和最小化,得到的系数β(τ)就是“第τ分位点的条件分位数回归系数”。

这里的关键直觉是:不同τ给正负残差分配了不同的相对权重。当τ=0.9时,模型更“在意”那些实际值很高、残差为正的样本点,所以系数会更贴近高收入人群的规律;当τ=0.1时,模型更关注低分位样本。这不是玄学,而是数学上让回归线去“贴合”不同部位的数据分布。理解了这个,后面看任何分位数回归结果都会顺很多。

2.2 系数到底怎么读:一个例子说清楚

我用一个经典例子来解释。假设你在研究教育年限(edu)对收入(income)的影响,跑出如下结果:

  • OLS:edu系数0.08,意为平均而言教育每多一年,收入提高8%
  • τ=0.10:edu系数0.03,意为收入第10百分位的人群里,教育每多一年,收入提高3%
  • τ=0.90:edu系数0.15,意为收入第90百分位的人群里,教育每多一年,收入提高15%

这三个数字放在一起,结论就非常生动:教育回报在低收入人群里并不高,但在高收入人群里非常显著。如果你只报OLS的0.08,等于把一个“两极分化”的故事讲成了一个乏味的平均故事。

需要注意一个细节:分位数回归的系数解释是“条件分位数”意义上的。也就是说,τ=0.90系数0.15,应该理解为“在控制其他变量后,预测收入分布第90分位点上,教育的影响是15%”,而不是“收入最高的那10%的人,他们的教育回报是15%”。前者的表述更严谨,后者在口语里说说可以,写论文还是尽量按条件分位数的口径来。

2.3 分位点的选择不是越密越好

很多初学者一上来就报5个甚至9个分位点,结果表格密密麻麻,审稿人看着也累。我的建议是,先根据研究问题确定核心关注的分布位置,一般选τ=0.10、0.25、0.50、0.75、0.90五个点就足够讲清楚故事了。如果你特别关心“底层人群”或“高分人群”,可以在对应区间加密,比如1%、5%这类极端分位。

另外,极端分位点(比如0.01、0.99)的估计通常不太稳定,因为那里的有效样本数量天然就少,标准误会显著变大。如果你非要报,请使用bootstrap标准误,并且对结果保持谨慎态度。我见过有人把τ=0.99的系数跑出来特别大,激动得不行,结果换一个随机种子,标准误区间能吞掉整个效应,这种结果拿出去很容易被质疑。

3. Stata实操:从准备环境到跑通第一个模型

3.1 开始之前:确认你的Stata环境和外部命令

分位数回归的基础功能不需要额外安装,qreg、bsqreg、sqreg这些命令都是Stata自带的。但后面要做可视化(grqreg)、面板数据分位数回归(xtqreg),就需要从外部安装。所以第一步建议确认一下网络和ado路径是否正常。

我自己最常用的安装命令是:

ssc install grqreg ssc install xtqreg ssc install qreg2

如果你用的是Stata 14以上版本,通常ssc仓库都能正常访问。装完之后输入:

which grqreg

能显示路径就说明装好了。遇到“command ... not found”的错误,先别慌,去查这个命令对应的ssc包名,经常会有人把“grqreg”和“grqreg”的拼写搞混,或者把帮助文件下载下来但没真正安装二进制文件,这些坑我都踩过。

还有一个容易被忽略的小事:Stata的版本会影响部分命令的语法。比如xtqreg早期版本只支持xtset后的面板数据,新版本做了不少改动。建议装完命令后用help xtqreg看一眼版本说明和示例,跑一遍自带示例再分析自己的数据,能节省大量排查时间。

3.2 数据探索:用summarize看分布,别急着回归

拿到数据后,第0步永远是看分布。你总得知道你的因变量到底在哪些区间集中、有没有极端异常值。Stata里最基础也最实用的命令:

summarize price weight mpg, detail

detail选项会输出最小值(min)、最大值(max)、几个分位点(1%、5%、10%、25%、50%、75%、90%、95%、99%)以及偏度峰度。这一步能帮你在跑模型前就形成直觉:哪些变量适合看低分位、哪些高分位更有故事。比如汽车价格,分布肯定右偏,你可能对高价位(高分位)的影响机制更感兴趣。

如果你需要生成变量层面的最大值最小值,可以配合egen命令:

egen min_price = min(price) egen max_weight = max(weight)

有时候在做分位数回归前,你想先剔除那些因为数据录入错误导致的极端值,比如收入变量出现负数、年龄出现300岁,这种清洗用egen加条件删除是最快的。别小看这一步,分位数回归虽然比OLS稳健,但极端异常值依然能让高分位的结果彻底失真。

3.3 qreg、sqreg、bsqreg到底怎么选

Stata里搞分位数回归,最常见的是三个命令:qreg、sqreg、bsqreg。很多新手在三个命令前面懵住,这里直接给结论:

  • qreg:最基础的分位数回归,一次只能估计一个τ,标准误基于残差绝对值函数的渐近理论。速度快,适合探索性分析。
  • bsqreg:在qreg基础上用bootstrap方法估计标准误,更稳健,但耗时较长。适合小样本或数据分布不规整的场景。
  • sqreg:同时估计多个分位点的模型,标准误可以通过bootstrap(reps指定次数)或scores计算,输出结果整齐,适合直接放进论文表格。

我的习惯是:探索阶段用qreg,分别跑几个核心分位点,看看系数大概的走势;正式分析用sqreg,一次性跑5个分位点,加上reps(200)做bootstrap标准误;如果样本量很小,我再补一个bsqreg做稳健性检验。三者结果应该高度一致,如果有明显出入,优先检查数据质量和模型设定,而不是盲目调整命令。

举个例子,用Stata自带的auto数据,跑不同分位点的价格对里程(mpg)的影响,基本命令就是:

sysuse auto, clear qreg price mpg weight, quantile(0.5)

这里quantile()用来指定分位点,默认是0.5,也就是中位数回归。中位数回归本身就是分位数回归里的一个特例,它对异常值的稳健性远优于OLS,这也是很多人第一次接触分位数回归的入口。

4. 完整案例:用auto数据做分位数回归

4.1 模型设定:我想看什么

为了把流程走通,我用Stata自带的auto数据来演示。这个数据集有1978年汽车的价格、里程、重量、维修记录等变量,变量不算复杂,但足够展示分位数回归的分析套路。研究问题设定为:汽车的重量和燃油效率(mpg)如何影响价格,并且这种影响在不同价格区间是否不同。

模型设定为: price = β0(τ) + β1(τ) × mpg + β2(τ) × weight + ε(τ) 分别在τ=0.10、0.25、0.50、0.75、0.90五个分位点估计。目标是看mpg(每加仑行驶英里数)的系数在哪里最大,weight的系数又在哪里最明显。对汽车市场来说,低价车市场和高价豪华车市场的定价逻辑很可能不一样,分位数回归正好可以端到端地看一遍。

4.2 跑模型:sqreg一次性搞定

我直接使用sqreg,把五个分位点和200次bootstrap一起指定:

sqreg price mpg weight, quantile(0.10 0.25 0.50 0.75 0.90) reps(200)

运行结束后,Stata会输出一个合并的结果表格,每一列对应一个分位点,每一行对应一个自变量的系数、标准误、t值和置信区间。这个表格的结构很清晰,可以直接复制到论文的附录或正文里。如果你想分开展示,也可以分别用qreg跑,但sqreg的优势在于它同时估计所有分位点,后续做跨分位点系数差异检验时更方便。

跑完命令后,我强烈建议你看一下左上角的样本量和bootstrap次数。如果reps(200)因为某些原因没跑满,输出里会有warning提示,这时候结果中的标准误并不可靠,需要加reps或检查数据的完整性问题。

4.3 读结果:系数在三个分位点上的变化

以mpg变量为例,假如输出显示:τ=0.10时系数-180(不显著),τ=0.50时系数-95(显著),τ=0.90时系数-350(显著),你的解读重点就不是“mpg对价格有负向影响”这种一句话结论,而要说“mpg的负向影响主要集中在高价位汽车,低价车市场mpg对定价的作用不明显”。这就是分位数回归最大的价值:你能看到一个效应是从哪儿开始起作用的,又在哪儿达到最强。

weight系数的解读同理。如果weight在低分位显著为正、高分位不显著,说明重量更多是低价车的定价支撑因素,到了豪华车区间,品牌、配置等未观测因素可能占据了主导。这种“效应转移”的发现,在实证论文里往往就是亮点。

还记得前面提到的最大值最小值处理吗?如果你在探索阶段发现price变量有异常值,比如某辆古董车价格高到离谱,建议先用egen和summarize找出这些点,判断是录入错误还是真实样本,再决定是缩尾还是剔除。这一步决定了高分位回归结果是否可信。

4.4 可视化:grqreg画出一条系数轨迹线

表格再清楚也不如图直观。我常用grqreg命令把某个变量的系数在多个分位点上的变化画成一条折线,并加上置信区间带。这样一眼就能看出系数是否随分位点单调变化,还是在某个位置突然反转。

ssc install grqreg grqreg mpg weight, ci

这里不加任何限定,grqreg默认会把你刚才sqreg里面的所有分位点系数画出来。如果你只想看某个变量,可以用:

grqreg mpg, ci ols

ols选项会在图上叠加一条OLS估计的系数水平线和置信区间,用来直观对比分位数回归与均值回归的差异。我看到很多人画图后才发现,原来OLS系数既不接近低分位也不接近高分位,而是悬在中间,这种视觉冲击比表格强烈得多。

如果要进一步做多变量系数对比,coefplot也可以胜任:

ssc install coefplot coefplot, keep(mpg weight) vertical bycoef

它会按变量分组,把每个分位点的系数画成点估计加置信区间的小图。具体用哪个命令看个人偏好,grqreg更专注于分位数结果,coefplot更通用。画图之后记得保存图像格式,Stata里graph export成PDF或PNG,宽度拉到8英寸以上,清晰度才够用。

5. 进阶场景:面板数据、工具变量与异质性分析的关系

5.1 面板数据里的分位数回归怎么跑

实际研究中,很多时候你手里的数据是面板结构,比如多年追踪的住户调查数据。普通qreg直接忽略了个体固定效应,会带来遗漏变量偏误。Stata里处理面板分位数回归的常用命令是xtqreg,使用前先声明面板结构:

xtset id year xtqreg y x1 x2, quantile(0.25 0.50 0.75) ls

其中ls选项表示用最小二乘估计作为初始值,能提高收敛速度。安装命令前面已经说过:

ssc install xtqreg

xtqreg的实现比较新,对于短面板或长面板都有对应的标准误处理方法。但注意,面板分位数回归在小样本下面表现不如普通分位数回归稳定,个体数太少时很容易不收敛。如果遇到收敛问题,优先减少分位点数、简化模型,或者改用qregpd、xtqr等替代命令。

我一直觉得,面板分位数回归是“锦上添花”型方法,不要一上来就用。先跑清楚混合截面分位数回归和普通面板固定效应模型,再看有没有必要引入分位数+面板的结合。引入之前想清楚审稿人可能会问“为什么不用分组交互项”这类问题,你需要有理有据地回答。

5.2 内生性问题:工具变量分位数回归

分位数回归同样面临内生性挑战。如果你的核心解释变量与误差项相关,各分位点的系数都会不一致。Stata里处理这个问题的常见命令是ivqreg(qreg2),它结合了工具变量思想,在不同分位点上用工具变量提取外生变异。

ssc install ivqreg ivqreg y x1 x2 (endog_var = instrument), quantile(0.50)

这种方法的代价是收敛难度大、结果对工具变量质量非常敏感。我的建议是:先用普通分位数回归做主分析,把工具变量分位数回归作为稳健性检验。另外,工具变量分位数回归的识别条件比较强,解释结果时要格外谨慎,很多审稿人会对极端分位的工具变量结果提出疑问。

如果你对“异质性分析”这个说法有共鸣,其实分位数回归就是最自然的异质性分析工具之一。很多论文里说的“亚组分析”,本质上就是在检验系数的异质性。但分位数回归的异质性是连续的、依赖于因变量分布位置的;亚组分析的异质性是离散的、依赖于分组变量。两者回答的问题维度不同,在写作中可以互为补充。我用分位数回归跑完发现效应集中在高分位后,再用亚组分析按收入中位数分组做个稳健性检验,审稿人基本上不会再挑“异质性被藏起来了”这种毛病。

5.3 分位数回归与交互项模型的对比

有同学习惯用“y对x、z、x×z”的交互项模型来检验异质性。这种方法可行,但它要求你得事先知道潜在异质性来源于哪个可观测变量z,而且你只能检验这一个维度。分位数回归不依赖分组变量选择,它让数据自动告诉你“效应在因变量的哪个区间更强”。当然,分位数回归也不是万能的,它对“位置”的解释比较抽象,不像交互项那样容易对应到具体的政策含义。最稳妥的做法是把两种方法都做了,结论互相印证,论文丰富度直接上一个档次。

6. 常见问题与排查技巧

6.1 不收敛、警告频出怎么办

分位数回归的不收敛问题,常见原因之一是数据里有太多完全相同的值(ties),尤其是离散型因变量。解决办法是检查因变量是不是连续变量,或者考虑加入jitter(微小随机扰动)再进行回归。还有一个原因是极端分位点上有效样本太少,遇到这种情况,要么减少分位点个数,要么直接用中位数回归代替极端分位。

如果sqreg跑很久还没出结果,先检查reps次数和数据量级。reps(200)在样本量几万条时是压力很大的,可以先reps(50)试跑,确认没有问题再加大次数。我自己的经验是,面板数据加入xtset之后,如果面板单位特别多,sqreg的bootstrap会显得异常慢,这时候可以改用qreg少跑几个分位点,或者用xtqreg专用命令来提速。

6.2 标准误选bootstrap还是scores

sqreg默认会自动计算标准误,如果你没有指定reps,它使用的是scores方法,计算快但假设较强。我个人的偏好是小样本下用bootstrap标准误,更稳健。Stata里写reps(200)即可,常见论文要求bootstrap次数至少200,如果你想更保险,500次也常见。注意bootstrap的随机性会导致每次运行标准误略有差异,结果里最好固定随机种子,让结果可复现:

set seed 12345

这个细节虽然不起眼,但能避免你第二天重新跑一遍结果不一样,也方便别人复核。

6.3 结果解读的几个翻车现场

翻车现场一:把条件分位数说成无条件分位数。论文里一定用“在控制其他变量后,处于价格分布第90百分位的汽车,mpg每提高1单位价格下降XX元”这类表述,别写成“价格最高的10%的汽车”。翻车现场二:拿高分位的系数跟低分位的系数直接做比较时,忘记做联合检验。虽然系数看起来一大一小,但可能亮横着的置信区间重叠很大,统计上并不显著。用test命令可以检验跨分位点系数差异:

test [q10]mpg = [q90]mpg

这条命令在sqreg的输出下可用,如果p值不显著,你就不能理直气壮地说“效应在不同分位点有显著差异”。

6.4 命令找不到、版本报错的通用排查

遇到command qreg is not found这种错误,虽然qreg是内置命令,但偶尔会因为Stata安装不完整或ado路径被污染而报错。先试:

which qreg

如果提示未找到,多半是Stata安装问题,而不是代码问题。对外部命令(grqreg、xtqreg等),报错大概率是没安或版本不对,用ssc install重新安装,并查看帮助文件确认命令语法是否与你手上的Stata版本匹配。我见过太多次因为Stata 13和Stata 16语法差异导致的“疑似命令失效”,其实不是命令没了,是版本接口变了。

7. 最后再分享一点我的个人经验

用分位数回归这几年,最大的体会是:这个工具真正改变人的不是“多跑了几条回归”,而是逼着你思考“你到底关心谁”。做政策评估也好,做机制检验也罢,一个平均值背后可能是完全不同的群体命运。分位数回归把你从“均值崇拜”里解放出来,让你看到数据背后的结构,这让它的价值远远超出“稳健性检验”的定位,而更像是理解现实复杂性的入口。

还有一个小技巧想送给刚开始上手的你:第一张图永远先画因变量的核密度分布,把分布形状刻在脑子里,再去选分位点。如果你能说出“这个变量在90分位附近有个小峰”,那你已经比绝大多数只会无脑跑五个分位点的人强很多了。工具始终是工具,真正重要的是你想讲一个什么样的故事,而分位数回归恰好是那个能帮你把故事讲得更有层次感的叙事工具。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 6:08:41

瑞芯微RV1126B实战:AI-ISP实现0.01Lux低光彩色成像

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:08:21

Excel模板自动计算AQI:线性插值与首要污染物识别全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:07:55

车牌字符识别实战:VOC数据集转YOLO格式与YOLOv8训练全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:07:41

MRAM与8位MCU工业存储方案:SPI驱动、掉电保护与实战避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/5 6:07:36

OVS性能解放之路:Mellanox ASAP2硬件卸载深度解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华