在使用 Stata 的 merge 命令进行数据匹配中,我们使用的最多的就是 1:1、 1:m 和 m:1 了,实际上上 merge 命令还支持 m:m 匹配,那么为什么不能用呢?当我们需要进行 m:m 匹配的时候我们又该如何操作呢?
首先我们可以通过三幅动图理解 1:1、 1:m 和 m:1 匹配:



是不是就很好理解了,那么为什么 m:m 不能使用呢,下面我们通过一个例子来讲解。
考虑下面两个示例数据:
* 考虑下面两个数据 clear input str10 name1 str3 gender "张三" "男" "李四" "男" "李梅" "女" "张楠" "女" end save mdata1, replace
clear input str10 name2 str3 gender "王五" "男" "赵四" "男" "王琴" "女" "赵英" "女" end save mdata2, replace
|
假如我们想得到所有同性别的组合,我们就需要进行 m:m 匹配,也就是我们最后应该得到 8 个观测值,但是我们看看直接用 m:m 的效果:
use mdata1, clear merge m:m gender using "mdata2"
|

结果我们只得到了四个观测值,例如“张楠-王琴”的组合就缺失了。那么如何才能得到我们想要的 8 种组合呢?
我们可以采取 m 次 1:m 的匹配,或者 m 次 m:1 的匹配(根据循环次数的多数判断,还是越少越好)。
首先统计 mdata1 种 gender 的 m 数,实际上也就是最大重复数量:
use mdata1, clear bysort gender: gen matchid = _n save mdata1, replace
|
这里每种性别都是两个人,所以下面循环两次即可:
forval i = 1/2 { use mdata1, clear keep if matchid == `i' merge 1:m gender using mdata2 save matchres`i', replace }
|
然后合并两次的结果:
use matchres1, clear append using matchres2 drop _m matchid
|
这样我们就得到了符合要求的结果:

另外也可以直接根据返回值里面的结果来建立循环:
use mdata1, clear cap drop matchid bysort gender: gen matchid = _n tab matchid ret list
local n = r(r) save mdata1, replace
forval i = 1/`n' { use mdata1, clear keep if matchid == `i' merge 1:m gender using mdata2 save matchres`i', replace }
use matchres1, clear forval i = 2/`n' { append using matchres`i' } drop _m matchid save resdata, replace
forval i = 1/`n' { cap erase matchres`i'.dta }
|
这样代码就更加智能了。
实际数据处理中我们也会经常遇到需要 m:m 匹配的情况,例如之前课程「使用 Stata 进行绿色专利的筛选」中,我们就用到了,本文中的案例也是取自该课程。感兴趣的小伙伴可以前往学习:
×
点击这里跳转到 RStata 短书平台获取附件:Stata 中如何正确地进行多对多匹配?
评论