# Stata：分组回归系数比较的新思路

Stata连享会   主页 || 视频 || 推文 || 知乎

New！ `lianxh` 命令发布了：

`. ssc install lianxh`

`. help lianxh`

⛳ Stata 系列推文：

## 1. 从 bdiff 命令的 “美中不足” 说起

### 1.1 两组变量对应相同的约束

``````. sysuse nlsw88.dta,clear
. set linesize 80     //设置表格展示的格式
. set cformat  %5.4f  //回归结果中系数和标准误的显示格式
. set sformat  %4.2f  //回归结果中 t 值的显示格式
. set pformat  %4.3f  //回归结果中 p 值的显示格式
. sum wage collgrad hours ttl_exp  married //描述性统计

Variable |        Obs        Mean    Std. dev.       Min        Max
-------------+---------------------------------------------------------
wage |      2,246    7.766949    5.755523   1.004952   40.74659
collgrad |      2,246    .2368655    .4252538          0          1
hours |      2,242    37.21811    10.50914          1         80
ttl_exp |      2,246    12.53498    4.610208   .1153846   28.88461
married |      2,246    .6420303    .4795099          0          1
``````

``````. gen lnwage=ln(wage)       //工资对数
. global xx "ttl_exp hours" //控制变量
. bdiff, group(married) model(reg lnwage collgrad \$xx) reps(500) bsample seed(123)

Variables |      b0-b1    Freq     p-value
-------------+-------------------------------
ttl_exp |     -0.003     379       0.242
married |      0.000     232       0.464
south |     -0.043     401       0.198
hours |      0.004      43       0.086
age |     -0.009     449       0.102
_cons |      0.221     109       0.218
---------------------------------------------
``````

``````. set seed 10101
. gen countyid=int(31*runiform()) //使用随机数生成区县代码 (1~30)
. recode countyid 10=. 20=. 30=. if married==1
. recode countyid 11=. 21=. 29=. if married==0
. bdiff, group(married) model(reg lnwage collgrad \$xx i.countyid) reps(500) bsample

conformability error
r(503);
``````

``````. drop countyid
. set seed 10101
. gen countyid=int(31*runiform()) //使用随机数生成区县代码 (1~30)
. recode countyid 10=. 20=. 30=. if married==1
. bdiff, group(married) model(reg lnwage collgrad \$xx i.countyid) reps(500) bsample

Note: The numbers of effective independent variables in Group1 (married=0) and g
> roup2 (married=1) are not equal
This may occur because you use the factor variable to indicate the dummy varaibl
> es
``````

## 2. 新思路：从 “面面俱到” 转向 “一心一意”

### 2.2 比较 AME 系数的组间差异

• 截面 OLS 模型设定下，AME 系数的组间差异显著性检验；
• 截面 Probit 或 Logit 模型设定下，AME 系数的组间差异显著性检验；
• 工具变量的两阶段最小二乘 (IV-TSLS) 设定下，AME 系数的组间差异显著性检验；
• 面板数据的线性固定效应 (FE-OLS) 模型设定下，AME 系数的组间差异显著性检验。

## 3. AME 系数的组间差异检验：截面 OLS

``````sysuse nlsw88.dta,clear          //导入示例数据
gen lnwage=ln(wage)              //生成工资对数
set seed 10101
gen countyid=int(31*runiform())  //使用随机数生成区县代码 (1~30)
recode countyid 10=. 20=. 30=. if married==1 //人为设置已婚组中缺失的虚拟变量
recode countyid 11=. 21=. 29=. if married==0 //人为设置未婚组中缺失的虚拟变量
global xx "ttl_exp hours i.countyid"        //控制变量的宏

*手动编写AME系数组间差异检验的命令
capture program drop AME_Linear      //清空历史命令
program define AME_Linear, eclass    //命令开始，将这段命令的名字定义为"AME_Linear"
preserve
tempname b b1 b0                   //定义三个用于临时存储的名字
reg lnwage collgrad \$xx i.countyid if married==1 //已婚组进行OLS回归
matrix `b1'=e(b)                //获取已婚组的平均边际效应b1(即已婚组的教育回报率)
reg lnwage collgrad \$xx i.countyid if married==0 //单身组进行OLS回归
matrix `b0'=e(b)                //获取单身组的平均边际效应b0 (即单身组的教育回报率)
matrix `b'=`b1'-`b0'            //获取两组样本的平均边际效应之差 (b1-b0)
ereturn post `b'
end
``````
``````. *使用Bootstrap方法运行上述命令"AME_Linear"，重复进行500次
. bootstrap _b, nowarn reps(500) seed(10101): AME_Linear

Bootstrap results                                        Number of obs = 2,246
Replications  =   500

------------------------------------------------------------------------------
|   Observed   Bootstrap                         Normal-based
| coefficient  std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
collgrad |    -0.0849     0.0598    -1.42   0.156      -0.2022      0.0323
------------------------------------------------------------------------------

. est store AME_diff_OLS //将组间差异检验的结果存储到"AME_diff_OLS"
``````

``````bootstrap _b，reps(规定重复抽样的次数) seed(设置随机数种子): 在冒号后填写自行编写的命令-例如"AME_Linear"
``````

`bootstrap` 命令将会对通过 `AME_Linear` 获得的平均边际效应之差 `(b1-b0)` 进行 500 次重复抽样，从而得到 `(b1-b0)` 的 Bootstrap 标准误、及其对应的 Z 值、P 值、95% 正态置信区间。我们据此可检验，collgrad 对应的 AME 系数是否在已婚组和未婚组之间存在显著差异。从 `bootstrap` 的运行结果看，检验统计量 Z 值为 -1.4，P 值大于 0.1，可认为 AME 系数在 10% 水平上并不存在显著差异。

``````. reg lnwage collgrad \$xx i.countyid if married==1
. est store AME_Group1_OLS     //保存已婚组的AME系数
. reg lnwage collgrad \$xx i.countyid if married==0
. est store AME_Group0_OLS     //保存单身组的AME系数
. esttab AME_Group1_OLS AME_Group0_OLS AME_diff_OLS,b(%9.4f) ///
>        se mtitle star(* 0.1 ** 0.05 *** 0.01) modelwidth(16)

------------------------------------------------------------------------
(1)                 (2)                 (3)
AME_Group1_OLS      AME_Group0_OLS        AME_diff_OLS
------------------------------------------------------------------------
(0.0314)            (0.0479)            (0.0598)
------------------------------------------------------------------------
N                        1325                 726                2246
------------------------------------------------------------------------
Standard errors in parentheses
* p<0.1, ** p<0.05, *** p<0.01
``````

## 4. AME 系数的组间差异检验：截面 Probit 与 Logit

``````. sum lnwage, d   //75%分位数为2.261
. gen highwage=(lnwage>=2.261)
. tab highwage    //得到新的二值结果变量，高收入=1，不是高收入=0

highwage |      Freq.     Percent        Cum.
------------+-----------------------------------
0 |      1,684       74.98       74.98
1 |        562       25.02      100.00
------------+-----------------------------------
Total |      2,246      100.00
``````

``````*手动编写AME系数组间差异检验的命令
capture program drop AME_Probit     //清空历史命令
program define AME_Probit, eclass   //命令开始，将这段命令的名字定义为"AME_Probit"
preserve
tempname b b1 b0                  //定义三个用于临时存储的名字
probit highwage collgrad \$xx i.countyid if married==1 //已婚组进行Probit回归
matrix `b1'=e(b)                 //获取已婚组的平均边际效应b1 (即已婚组的教育回报率)
probit highwage collgrad \$xx i.countyid if married==0 //单身组进行Probit回归
matrix `b0'=e(b)                 //获取单身组的平均边际效应b0 (即单身组的教育回报率)
matrix `b'=`b1'-`b0'             //获取两组样本的平均边际效应之差 (b1-b0)
ereturn post `b'
end
``````
``````. *使用Bootstrap方法运行上述命令"AME_Probit"，重复进行500次
. bootstrap _b, nowarn reps(500) seed(10101): AME_Probit

Bootstrap results                                        Number of obs = 2,246
Replications  =   500
------------------------------------------------------------------------------
|   Observed   Bootstrap                         Normal-based
| coefficient  std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
collgrad |    -0.0338     0.0343    -0.98   0.325      -0.1010      0.0334
------------------------------------------------------------------------------

. est store AME_diff_Probit //将组间差异检验的结果存储到"AME_diff_Probit"
``````

`bootstrap` 的运行结果看，检验统计量 Z 值为-0.985，P 值大于 0.1，可认为 AME 系数在 10% 水平上并不存在显著差异。类似地，为了更直观地展示 collgrad 在已婚样本、单身样本中的平均边际效应及其组间差异，我们可以使用 `est store``esttab` 命令。

``````. probit highwage collgrad \$xx i.countyid if married==1
. est store AME_Group1_Probit     //保存已婚组的AME系数
. probit highwage collgrad \$xx i.countyid if married==0
. est store AME_Group0_Probit     //保存单身组的AME系数
. esttab AME_Group1_Probit AME_Group0_Probit AME_diff_Probit, ///
>        b(%9.4f) se mtitle star(* 0.1 ** 0.05 *** 0.01) modelwidth(16)

------------------------------------------------------------------------
(1)                 (2)                 (3)
AME_Group1_Pro~t    AME_Group0_Pro~t     AME_diff_Probit
------------------------------------------------------------------------
(0.0194)            (0.0268)            (0.0343)
------------------------------------------------------------------------
N                        1325                 726                2246
------------------------------------------------------------------------
Standard errors in parentheses
* p<0.1, ** p<0.05, *** p<0.01
``````

## 5. AME 系数的组间差异检验：引入工具变量

``````. gen e=rchi2(3)-3
. gen Z_instrument=0.3+3.5*collg+e  //生成有效的工具变量，与原因变量相关，与误差项无关
``````

``````*手动编写AME系数组间差异检验的命令
capture program drop AME_TSLS     //清空历史命令
program define AME_TSLS, eclass   //命令开始，将这段命令的名字定义为"AME_TSLS"
preserve
tempname b b1 b0                 //定义三个用于临时存储的名字
ivreg2 lnwage (collgrad=Z) \$xx i.countyid if married==1 //已婚组进行TSLS回归
matrix `b1'=e(b)                 //获取已婚组的平均边际效应b1 (即已婚组的教育回报率)
ivreg2 lnwage (collgrad=Z) \$xx i.countyid if married==0 //单身组进行TSLS回归
matrix `b0'=e(b)                 //获取单身组的平均边际效应b0 (即单身组的教育回报率)
matrix `b'=`b1'-`b0'             //获取两组样本的平均边际效应之差 (b1-b0)
ereturn post `b'
end
``````
``````. *使用Bootstrap方法运行上述命令"AME_TSLS"，重复进行500次
. bootstrap _b, nowarn reps(500) seed(10101): AME_TSLS

Bootstrap results                                        Number of obs = 2,246
Replications  =   500

------------------------------------------------------------------------------
|   Observed   Bootstrap                         Normal-based
| coefficient  std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
collgrad |    -0.1623     0.1082    -1.50   0.134      -0.3744      0.0498
------------------------------------------------------------------------------

. est store AME_diff_TSLS //将组间差异检验的结果存储到"AME_diff_TSLS"
``````

``````. ivreg2 lnwage (collgrad=Z) \$xx i.countyid if married==1,r
. est store AME_Group1_TSLS     //保存已婚组的AME系数
. ivreg2 lnwage (collgrad=Z) \$xx i.countyid if married==0,r
. est store AME_Group0_TSLS     //保存单身组的AME系数
. esttab AME_Group1_TSLS AME_Group0_TSLS AME_diff_TSLS,b(%9.4f) ///
>        se mtitle star(* 0.1 ** 0.05 *** 0.01) modelwidth(16)

------------------------------------------------------------------------
(1)                 (2)                 (3)
AME_Group1_TSLS     AME_Group0_TSLS       AME_diff_TSLS
------------------------------------------------------------------------
(0.0615)            (0.0884)            (0.1082)
------------------------------------------------------------------------
N                        1325                 726                2246
------------------------------------------------------------------------
Standard errors in parentheses
* p<0.1, ** p<0.05, *** p<0.01
``````

## 6. AME 系数的组间差异检验：面板数据的线性固定效应情形

``````. cnssc install bcuse, replace
. bcuse nls81_87.dta, clear
. gen newid=id //生成新的个体标识变量
. xtset newid year // 设置面板数据格式，注意panel name应该用newid而不是原有的id变量
. gen lnwage=ln(wage)  //生成工资对数
``````
``````*手动编写AME系数组间差异检验的命令
capture program drop AME_Panel     //清空历史命令
program define AME_Panel, eclass   //命令开始，将这段命令的名字定义为"AME_Probit"
preserve
tempname b b1 b0                  //定义三个用于临时存储的名字
xtreg lnwage exper c.exper#c.exper i.year if manuf==1,fe  //制造业组进行FE回归
margins,dydx(exper) post
matrix `b1'=e(b)                 //获取制造业组的平均边际效应b1
xtreg lnwage exper  c.exper#c.exper i.year if manuf==0,fe  //非制造业组进行FE回归
margins,dydx(exper) post
matrix `b0'=e(b)                 //获取非制造业组的平均边际效应b0
matrix `b'=`b1'-`b0'             //获取两组样本的平均边际效应之差 (b1-b0)
ereturn post `b'
end                                //自己编写的命令到此结束
``````
``````. *使用Bootstrap方法运行上述命令"AME_Panel"，重复进行500次。
. bootstrap _b, cluster(id) idcluster(newid) nowarn reps(500) seed(10101): AME_Panel

Bootstrap results                                        Number of obs = 3,710
Replications  =   500

(Replications based on 530 clusters in id)
------------------------------------------------------------------------------
|   Observed   Bootstrap                         Normal-based
| coefficient  std. err.      z    P>|z|     [95% conf. interval]
-------------+----------------------------------------------------------------
exper |     0.0805     0.0716     1.12   0.261      -0.0599      0.2208
------------------------------------------------------------------------------

. est store AME_diff_FE //将组间差异检验的结果存储到"AME_diff_FE"
``````

``````. xtreg lnwage exper c.exper#c.exper i.year if manuf==1,fe vce(cl id)  //制造业组进行FE回归
. margins,dydx(exper) post
. est store AME_Group1_FE     //保存制造业组的AME系数
. xtreg lnwage exper c.exper#c.exper i.year if manuf==0,fe vce(cl id)  //非制造业组进行FE回归
. margins,dydx(exper) post
. est store AME_Group0_FE     //保存非制造业组的AME系数
. esttab AME_Group1_FE AME_Group0_FE AME_diff_FE,b(%9.4f) ///
>        se mtitle star(* 0.1 ** 0.05 *** 0.01) modelwidth(16)

------------------------------------------------------------------------
(1)                 (2)                 (3)
AME_Group1_FE       AME_Group0_FE         AME_diff_FE
------------------------------------------------------------------------
exper                  0.1624***           0.0820*             0.0805
(0.0493)            (0.0440)            (0.0716)
------------------------------------------------------------------------
N                         650                1606                3710
------------------------------------------------------------------------
Standard errors in parentheses
* p<0.1, ** p<0.05, *** p<0.01
``````

## 8. 参考资料

• Cameron, A. Colin, and Douglas L. Miller. "A practitioner’s guide to cluster-robust inference." Journal of Human Resources 50.2 (2015): 317-372. -PDF
• Mize, Trenton D., Long Doan, and J. Scott Long. "A general framework for comparing predictions and marginal effects across models." Sociological Methodology 49.1 (2019): 152-189. -PDF
• Wooldridge, Jeffrey M. Econometric analysis of cross section and panel data. MIT press, 2010.
• 陈强, 2014. 高级计量经济学及 Stata 应用(第二版)[M]. 高等教育出版社.
• 洪岩璧. 2015. Logistic 模型的系数比较问题及解决策略：一个综述[J]. 社会, 35(4): 220-241.
• 连玉君, 廖俊平. 如何检验分组回归后的组间系数差异？[J]. 郑州航空工业管理学院学报, 2017, 35(6): 97-109.

## 9. 相关推文

Note：产生如下推文列表的 Stata 命令为：
`lianxh 分组回归 边际效应 cluster, m`

`ssc install lianxh, replace`

## 相关课程

### 最新课程-直播课

• Note: 部分课程的资料，PPT 等可以前往 连享会-直播课 主页查看，下载。

### 关于我们

• Stata连享会 由中山大学连玉君老师团队创办，定期分享实证分析经验。
• 连享会-主页知乎专栏，400+ 推文，实证分析不再抓狂。直播间 有很多视频课程，可以随时观看。
• 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标，输入简要关键词，以便快速呈现历史推文，获取工具软件和数据下载。常见关键词：`课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法`

✏ 连享会-常见问题解答：
https://gitee.com/lianxh/Course/wikis

New！ `lianxh` 命令发布了：

`. ssc install lianxh`

`. help lianxh`