Stata 中如何正确地进行多对多匹配?

在使用 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
* 可以看到循环次数就存储在 r(r) 里面
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 中如何正确地进行多对多匹配?

评论