数据清洗|数据匹配、接驳
相关命令:
- "append": 数据纵向接驳
- "merge": 精确数据匹配
- "reclink"](siyuan://blocks/20220406230229-pmnxtfx): 模糊数据匹配
- "joinby": 多对多的匹配
- "nearmrg": 相似值的匹配
其中,reclink
、joinby
、nearmrg
的用法来自:
Stata:数据合并与匹配-merge-reclink| 连享会主页 (lianxh.cn)
其他命令:
mergemany
、mergeall
mergemany -- 一个灵活的命令来合并许多文件 - 简书 (jianshu.com)
mergeall -- 合并多个文件的安全方法 - 简书 (jianshu.com)
一、数据接驳: append
数据接驳是数据集的纵向扩展,将不同的数据集纵向拼接在一起。
- 数据匹配使用
append
命令。与merge
不同,数据接驳append
命令不需要指定识别变量; - 当前使用的数据是 master data,
append
命令可以生成一个结果变量注明样本的来源; - 在接驳的数据集中,变量名相同的变量的值将保存在同一变量名下。
基本语法:
1 | append using filename [filename ...] [, options] |
所有选项 options:
append
的选项大多与 merge
命令相同。
1 | /*Options: |
比较常用的 options 是
keepus(varlist)
、gen(newvar)
。
示例:
(⚠️注意:不同设备的显示字体不同,可能会出现字符错位的现象。将错位的文本复制到其他文本编辑器 / Stata do 文件编辑器中,可以解决此问题。)
1 | use "data1.dta" |
二、精确数据匹配: merge
数据匹配是数据集的横向扩展,通过识别某些变量在不同数据集中的对应关系,将其他数据集的一些变量匹配到当前数据中。
- 数据匹配使用
merge
命令,当前打开的数据称为 master data,待匹配的数据称为 using data; - 数据匹配包含 1:1,1:m,m:1,m:m 四种类型;
- 在匹配完成后,会生成一个显示匹配结果的变量,默认是“_merge”。
基本语法:
1 | merge X:X varlist using filename [, options] |
所有选项 options:
1 | /*Options: |
merge
命令一般使用 options 较少,比较常用的 options
是 keepus(varlist)
、gen(newvar)
。
匹配结果:
不论哪种匹配方式,生成的匹配结果变量会有三个固定的取值:
_merge=1:未匹配成功,该样本的数据仅来自 master data;
_merge=2:未匹配成功,该样本的数据仅来自 using data;
_merge=3:匹配成功,该样本的数据同时来自 master data 和 using data;
因此,可以根据匹配结果变量的取值,筛选出需要的样本:
1 | ** 不删除任何样本,直接删除_merge变量 |
第一种:one-to-one merge
使用 1:1 匹配的条件:用于匹配的 varlist 在 master data 和 using data 中可以唯一识别每一个样本。若某一个变量不能唯一识别每个样本,则要求通过多个变量可以唯一识别两套数据中的每一个样本。
示例:
1 | use "master_data.dta" |
第二种:one-to-many merge
使用 1:m 匹配的条件:用于匹配的 varlist 在 master data 中可以唯一识别每一个样本,且在 using data 中对应多个样本。
常见使用场景:
- master data 是家庭数据,using data 是个体数据,一个家庭对应多个个体,使用家庭的编码进行识别;
- master data 是省级数据,using data 是地级市数据,一个省对应多个地级市,使用省份的编码进行识别。
示例:
1 | use "master_data.dta" |
第三种:many-to-one merge
将 1:m 匹配中的 master data 和 using data 的数据特征互换时,就应该使用 m:1 匹配。
使用 m:1 匹配的条件:用于匹配的 varlist 在 using data 中可以唯一识别每一个样本,且在 master data 中对应多个样本。
常见使用场景:
- master data 是个体数据,using data 是家庭数据,多个个体可以同时在一个家庭内,使用家庭的编码进行识别;
- master data 是地级市数据,using data 是省级数据,多个地级市同属于一个省份,使用省份的编码进行识别。
示例:
1 | use "master_data.dta" |
第四种:many-to-many merge
m:m 匹配不建议使用,因为其匹配结果是不确定的!
在数据匹配时,多数情况使用 1:1、1:m、m:1 已经可以解决问题。此处不再展示 m:m 的用法。
三、模糊数据匹配: reclink (字符串的模糊匹配)
在横向合并时,若匹配变量在内容上有些差别,如在第一份数据中为「Princeton
University」,而在第二份数据中为「Princeton U」,我们可以通过
reclink
命令快速模糊匹配,以避免繁琐的人工识别。具体示例如下:
1 | *输入两份数据 |
模糊匹配后结果:
1 | name Uname city Ucity id1 matchs~e id2 _merge |
reclink
命令注意事项 :
- 两份数据中 id 名必须不同。如,在上述命令中
idmaster(id1)
、idusing(id2)
分别代表 master data 中的 id 和 using data 中的 id ,结果第五列和第七列解读为 master data中的id1 = 1 和 using data 中的 id2 = 1 匹配成功; - **_merge** 变量含义与前文类似;
reclink
命令可解决的匹配问题:大小写不同、部分字母缺漏或增加、以及顺序颠倒;- matchscore 变量为匹配分数,分数越高代表匹配效果越好。
另外,reclink
命令还允许对匹配变量设定不同权重。比如,在这个例子中,我们认为
city 是最重要的,则仅需增加 vmatch()
选项设定权重。具体示例如下:
1 | use file1.dta,clear |
模糊匹配后结果:
1 | name Uname city Ucity id1 matchs~e id2 _merge |
可以看出,该结果与前文结果具有一定差异。
当然,模糊匹配也可以使用 matchit
命令。更多有关
reclink
与matchit
的介绍请参考「Stata:模糊匹配之matchit」。
四、多对多的匹配: joinby
在进行多对多匹配时,我们可以使用 merge
或
joinby
命令,但二者又具有哪些差别?具体示例如下:
1 | *输入数据 |
merge
命令多对多匹配结果:
1 | group x1 x2 _merge |
可以看出,merge
命令的多对多合并是有问题的,其会以较少数据文件的最后一行值 (比如这里的
file2.dta 的最后一行数据「group1,x2=N」) 进行重复合并。
joinby
命令多对多匹配结果:
1 | group x1 x2 |
可以看出,joinby
命令显然更符合我们的要求。关于
joinby
命令更多详细介绍,请查看帮助文件
help joinby
。
五、nearmrg 命令:相似值的匹配
上文已经介绍了字符串模糊匹配命令
reclink
,这里再介绍一下数值模糊匹配命令
nearmrg
。关于该命令更多介绍,请查看帮助文件
help nearmrg
。
1 | *生成一份数据 |
列出数据:
1 | make2 price mpg |
然后,我们将该数据与 auto.dta 进行合并,并找出 using.dta 数据中价格浮动在 $50 上下的数据。
1 | sysuse auto.dta, clear |
1 | make price mpg make2 _merge usingm~h |
可以看出,using data 中原有 5 行数据,合并后变成了 9 行数据。之所以如此,是因为 auto.dta 中价格浮动在 50 之内的数据都被保留了下来。