? 连享会主页:lianxh.cn


? 因果推断-内生性 专题   ⌚ 2020.11.12-15
? 主讲: 王存同 (中央财经大学);司继春(上海对外经贸大学)
? 课程主页:https://gitee.com/arlionn/YG
? 诚邀助教 10 名,详见课程主页。


作者:刘涛 (中山大学岭南学院)
邮箱:liut75@mail2.sysu.edu.cn


目录[

  • 1. 问题描述

  • 2. 解决方法

  • 3. 哪种方法好?

  • 4. 总结

  • 5. 参考资料

  • 附: 伍德里奇老兄的提问原文


NEW!连享会·推文专辑:
Stata资源 | 数据处理 | Stata绘图 | Stata程序
结果输出 | 回归分析 | 时间序列 | 面板数据 | 离散数据
交乘调节 | DID | RDD  |  因果推断 |  SFA-TFP-DEA
文本分析+爬虫 | 空间计量 | 学术论文 | 软件工具

连享会学习群-常见问题解答汇总:
?  WD 主页:https://gitee.com/arlionn/WD

写在前面: 相信《小蝌蚪找妈妈》是不少人的童年回忆。在数据处理中,我们常常需要处理像「小蝌蚪」要找到「妈妈」的数据,并将它们成功匹配。

本文将借助 伍德里奇教授statalist 论坛的 提问和后续讨论 来讲讲利用 Stata 数据处理中「小蝌蚪」找到「妈妈」的故事。

在推文的末尾,我们也附上了伍德里奇教授在论坛里提问时的原贴。我们能从中能够感受到严谨的治学态度。即使是提出这么一个简单的问题,他也会花大量的篇幅来描述问题的背景,并附上自己测试的一些代码,以便让其他坛友花最短的时间了解问题背景。这即可以节省他人的时间,也有助于自己尽快获取有用的反馈信息。

温馨提示: 文中链接在微信中无法生效。请点击底部

1. 问题描述

我们手头有如下面板数据(精简版):

  +-----------------------------+  | id   year   nb1   nb2     x |  |-----------------------------|  |  1   2000     2     3   100 |  |  1   2001     2     3   110 |  |  1   2002     2     3   120 |  |-----------------------------|  |  2   2000     1     4   200 |  |  2   2001     1     4   210 |  |  2   2002     1     4   220 |  |-----------------------------|  |  3   2000     4     .   300 |  |  3   2001     4     .   310 |  |  3   2002     4     .   320 |  |-----------------------------|  |  4   2000     3     2   400 |  |  4   2001     3     2   410 |  |  4   2002     3     2   420 |  +-----------------------------+

该样本源于一个社区调查,共有四户居民,其中 id 为编号,year 为调查年份,nb1 为其邻居一 neighbor1idnb2 为其邻居二 neighbor2 的编号。以第一个样本为例,其 nb1=2nb2=3,说明第二户和第三户居民是其邻居。x 值是调查值,可以理解为收入。现在,我们需要做的工作就是,将样本对应的邻居的 x 值匹配到数据中来,即让样本找到其邻居的数据,来构造一个协变量。最终想要的结果如下:

  +---------------------------------------------+  | id   year   nb1   nb2     x   x_nb1   x_nb2 |  |---------------------------------------------|  |  1   2000     2     3   100     200     300 |  |  1   2001     2     3   110     210     310 |  |  1   2002     2     3   120     220     320 |  |---------------------------------------------|  |  2   2000     1     4   200     100     400 |  |  2   2001     1     4   210     110     410 |  |  2   2002     1     4   220     120     420 |  |---------------------------------------------|  |  3   2000     4     .   300     400       . |  |  3   2001     4     .   310     410       . |  |  3   2002     4     .   320     420       . |  |---------------------------------------------|  |  4   2000     3     2   400     300     200 |  |  4   2001     3     2   410     310     210 |  |  4   2002     3     2   420     320     220 |  +---------------------------------------------+

接下来,我们将基于论坛中SebastianRobert 提出的解决方法,来介绍如何巧妙地使用 Stata 中的 MergeRangestat 的命令来解决上述问题。

这些解决思路在 PSM (Propensity Score Matching,倾向得分匹配分析) 中非常有用。例如,对于文献中普遍使用的 PSM-DID 方法中,最为棘手的问题就是如何在完成 PSM 分析后,把 实验组(Treat group)对照组(Control group) 的样本对应起来,以便做后续的 DID (倍分法, 双重差分) 分析。

2. 解决方法

先将原始数据存储起来:

*-----------balance data---------------clearinput ///id year nb1 nb2 x1  2000  2  3  1001  2001  2  3  1101  2002  2  3  1202  2000  1  4  2002  2001  1  4  2102  2002  1  4  2203  2000  4  .  3003  2001  4  .  3103  2002  4  .  3204  2000  3  2  4004  2001  3  2  4104  2002  3  2  420endsave "Peer_Woold_balance", replace*-------------------------------------

2.1 方法 1:公式求解


根据 *Sebastian 的方法,我们可以将原始的数据按 idyear 排序,之后通过 nb1 的值构造出对应公式,找出数组中的下标,从而代入完成匹配。代码如下:

use "Peer_Woold_balance", clearsort id year           //排序by id: gen n = _n       //按id生成序列,即1,2,3分别代表不同的年份local N = n[_N]           //生成暂元,记录固定的N=3gen x_nb1 = x[(nb1 - 1) * `N' + n] //匹配nb1的数据gen x_nb2 = x[(nb2 - 1) * `N' + n] //匹配nb2的数据drop n

该方法的关键之处就是构造出了 (nb1-1)N + n 这个公式来计算下标。因为排序过后,x 是一个按 idyear 排序的序列,只要代入下标,就能得到对应的值。如,当 nb1=3 时,我们就要取 x 中的第 7 位到第 9 位,(nb1-1)*3 得到 6,再分别加序列 1,2,3 即得到我们想要的结果。

2.2 方法 2:使用 Merge 命令进行匹配

通常我们在匹配数据时,我们可能会想到 Excel 中万能的 VLOOKUP 函数:

VLOOKUP(要查找的值,查找范围,返回值的位置,精确匹配)

其实,stata 中的 Merge 命令也能实现该功能。

  • Merge 命令常用来进行数据集的合并,即从外部数据文件中,增加变量,它主要有四种方式来进行合并:
  1. 1:1 合并
. merge 1:1 varlist using filename [, options]
  1. m:1 合并
. merge m:1 varlist using filename [, options]
  1. 1:m 合并
. merge 1:m varlist using filename [, options]
  1. m:m 合并
. merge m:m varlist using filename [, options]

其中,varlist 则是用来唯一标示每一行观察值的一个或一组的变量。

Robert 认为,可以将 nb1、nb2 对应的数据单独导出为一个数据文件,再通过 Merge命令,通过 idyear 来识别每一行观察值,从而将 nb1nb2 的数值对应横向合并到原有数据集中。

* 保存 nb1 的数据集use "Peer_Woold_balance", clearkeep id year xrename (id x) (nb1 x_nb1)save "nb1.dta", replace

* 保存 nb2 的数据集use "Peer_Woold_balance", clearkeep id year xrename (id x) (nb2 x_nb2)save "nb2.dta", replace

* 回到原始的数据集 Peer_Woold_balance.dta,进行横向合并use "Peer_Woold_balance", clearmerge m:1 nb1 year using "nb1.dta", keep(master match) nogen //nogen是设定不生成_Merge的指示变量。merge m:1 nb2 year using "nb2.dta", keep(master match) nogenisid id year, sort      //按id、year排序list, sepby(id)

这是通过 Merge 的实现方法,更为具体的功能可以 help merge 深入了解。

2.3 方法 3:使用 rangestat 命令

除了 Merge 之外,Robert 也提出了借助 Rangestat 来解决数据匹配问题的方法。

根据 Stata 帮助文件的定义:rangestat 命令主要用于针对特定的观察值进行相关的统计工作,格式如下:

. rangestat (stat) varname, interval(keyvar low high) [options]

主要选项的含义如下:

  • (stat): 常常是你所要进行的统计工作,如求最小值 min,均值 mean 等等
  • varname: 即是所进行统计的变量
  • interval(): 则是选定数据的范围

如下例子则可以对 rep78 筛选后的数据,统计 pricempg 变量的最小值、均值等:

sysuse auto, clearrangestat (min) price mpg (mean) price mpg, interval(rep78 0 0)

由于我们的数据是面板数据,其中要通过 idyear 两个变量来确定样本, 而 rangestat 筛选条件只有一个,因此,我们可以通过创建一个新变量来包含上述 idyear 的信息。在这里,类似于创建我们的学号,如 15353333,15 代表入学年份,35 代表院系,3333 代表学生顺序,创建了 12000、12001 等变量。

gen double bigid= id*10000+yeargen double idyear=nb1*10000+year

在将创建完新的变量之后,我们需要将 idyearbigid 进行匹配, 将那些 bigid 的值等于当前 idyear 的观察值找出来,interval(bigid idyear idyear) 命令可以完美实现这个功能。

rangestat (min) x_nb1=x,interval(bigid idyear idyear)//以第一个样本为例,idyear=22000,rangestat通过这个语句,就能在bigid这一变量中找到bigid=22000的样本,之后对其进行统计。replace idyear = nb2 * 10000 + yearreplace idyear = 0 if mi(idyear)rangestat (min) nb_2=x, interval(bigid idyear idyear)list, sepby(id)

3. 哪种方法好?

表面上看起来第一种方法似乎最为简洁,但第二种方法的思路最为清晰。对于任何一种方法,我们的主要评价依据是该方法是否有通用性。以此来判断,第二种方法的通用性是最强的。这是因为,第一种方法只适用于平行面板数据,而在实际的匹配过程中,我们的数据往往是非平行面板。大家可以考虑一下非平行面板的情形:

  +-----------------------------+  | id   year   nb1   nb2     x |  |-----------------------------|  |  1   2000     2     3   100 |  |  1   2001     2     3   110 |  |-----------------------------|  |  2   2000     1     4   200 |  |  2   2001     1     4   210 |  |  2   2002     1     4   220 |  |-----------------------------|  |  3   2000     4     .   300 |  |  3   2001     4     .   310 |  |  3   2002     4     .   320 |  |-----------------------------|  |  4   2000     3     2   400 |  |  4   2001     3     2   410 |  |  4   2002     3     2   420 |  |  4   2003     .     .   430 |  +-----------------------------+

此时,第一种方法得到的结果是错乱的(当然,可能需要重新构造公式):

  +---------------------------------------------+  | id   year   nb1   nb2     x   x_nb1   x_nb2 |  |---------------------------------------------|  |  1   2000     2     3   100     220     400 |  |  1   2001     2     3   110     300     410 |  |---------------------------------------------|  |  2   2000     1     4   200     100       . |  |  2   2001     1     4   210     110       . |  |  2   2002     1     4   220     200       . |  |---------------------------------------------|  |  3   2000     4     .   300       .       . |  |  3   2001     4     .   310       .       . |  |  3   2002     4     .   320       .       . |  |---------------------------------------------|  |  4   2000     3     2   400     400     220 |  |  4   2001     3     2   410     410     300 |  |  4   2002     3     2   420     420     310 |  |  4   2003     .     .   430       .       . |  +---------------------------------------------+

相对而言,第二种方法仍然可以得到正确结果:

*-----------unbalance data---------------clearinput ///id year nb1 nb2 x1  2000  2  3  1001  2001  2  3  1102  2000  1  4  2002  2001  1  4  2102  2002  1  4  2203  2000  4  .  3003  2001  4  .  3103  2002  4  .  3204  2000  3  2  4004  2001  3  2  4104  2002  3  2  4204  2003  .  .  430end*---------------------------------------save "Peer_Woold_unbalance", replacelist, sepby(id) noobs

*-----------*-2.2 方法2:使用 Merge 命令进行匹配

* 保存nb1的数据集

  use "Peer_Woold_unbalance", clear  keep id year x  rename (id x) (nb1 x_nb1)  save "nb1.dta", replace

* 保存nb2的数据集  use "Peer_Woold_unbalance", clear  keep id year x  rename (id x) (nb2 x_nb2)  save "nb2.dta", replace

* 回到原始的数据集main.dta,进行横向合并  use "Peer_Woold_unbalance", clear  merge m:1 nb1 year using "nb1.dta", keep(master match) nogen //nogen是设定不生成_Merge的指示变量。  merge m:1 nb2 year using "nb2.dta", keep(master match) nogen  isid id year, sort      //按id、year排序  list, sepby(id)

结果如下:

  +---------------------------------------------+  | id   year   nb1   nb2     x   x_nb1   x_nb2 |  |---------------------------------------------|  |  1   2000     2     3   100     200     300 |  |  1   2001     2     3   110     210     310 |  |---------------------------------------------|  |  2   2000     1     4   200     100     400 |  |  2   2001     1     4   210     110     410 |  |  2   2002     1     4   220       .     420 |  |---------------------------------------------|  |  3   2000     4     .   300     400       . |  |  3   2001     4     .   310     410       . |  |  3   2002     4     .   320     420       . |  |---------------------------------------------|  |  4   2000     3     2   400     300     200 |  |  4   2001     3     2   410     310     210 |  |  4   2002     3     2   420     320     220 |  |  4   2003     .     .   430       .       . |  +---------------------------------------------+

第三种方法留待各位读者自行测试。

4. 总结

通过介绍伍德里奇教授在 Statalist 的提问,想必大家对如何利用 mergerangestat命令帮助「小蝌蚪」数据们找到了「妈妈」有了一定的了解。当然,在数据处理中,问题是复杂的,解决问题的方法是多样的,大家若有新的想法或是问题,也希望大家与 Stata 连享会进行交流,共同进步。

5. 参考资料


  • Statalist 论坛讨论
  • Stata 帮助手册

附: 伍德里奇老兄的提问原文

Jeff Wooldridge,01 May 2016, 10:00 Hi All:

I have a problem where I have a (balanced) panel data set, and each cross-sectional unit in the data set comes with two neighbors, contained in the variables nb1 and nb2 (although some neighbor values are missing). I'd like to put the values of some of the neighbors' covariates on the proper line so I can include them in regression analysis. I know how to do this without a panel structure, and I found a recent helpful entry by Nick Cox that confirms what I thought. But I'm stuck for the panel data case.

The identities of the neighbors do not change over time.

The first block below gives a simple example of the structure, and the second block gives what I would like to have. I'd really appreciate any hints. Thanks, Jeff.

Code:

id year nb1 nb2 x

1 2000 2 3 1001 2001 2 3 1101 2002 2 3 1202 2000 1 4 2002 2001 1 4 2102 2002 1 4 2203 2000 4 . 3003 2001 4 . 3103 2002 4 . 3204 2000 3 2 4004 2001 3 2 4104 2002 3 2 420

id year nb1 nb2 x x_nb1 x_nb2

1 2000 2 3 100 200 3001 2001 2 3 110 210 3101 2002 2 3 120 220 3202 2000 1 4 200 100 4002 2001 1 4 210 110 4102 2002 1 4 220 120 4203 2000 4 . 300 400  .3 2001 4 . 310 410  .3 2002 4 . 320 420  .4 2000 3 2 400 300 2004 2001 3 2 410 310 2104 2002 3 2 420 320 220

? 空间计量 专题   ⌚ 2020.12.10-13
? 主讲:杨海生 (中山大学);范巧 (兰州大学)
? 课程主页:https://gitee.com/arlionn/SP | 微信版



? ? ? ?
连享会主页:? www.lianxh.cn
直播视频:lianxh.duanshu.com

免费公开课:

  • 直击面板数据模型:https://gitee.com/arlionn/PanelData - 连玉君,时长:1小时40分钟
  • Stata 33 讲:https://gitee.com/arlionn/stata101 - 连玉君, 每讲 15 分钟.
  • 部分直播课课程资料下载 ? https://gitee.com/arlionn/Live (PPT,dofiles等)

温馨提示: 文中链接在微信中无法生效。请点击底部


关于我们

  • ? 连享会 ( 主页:lianxh.cn ) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • ? 直达连享会:百度一下:连享会】即可直达连享会主页。亦可进一步添加 主页,知乎,面板数据,研究设计 等关键词细化搜索。

连享会主页  lianxh.cn

?  连享会小程序:扫一扫,看推文,看视频……



? 扫码加入连享会微信群,提问交流更方便


? 连享会学习群-常见问题解答汇总:
?  https://gitee.com/arlionn/WD

stata psm命令_伍德里奇先生的问题:PSM的配对小蝌蚪找妈妈相关推荐

  1. 伍德里奇先生的问题:PSM-分析中的配对——小蝌蚪找妈妈

    全文阅读:https://www.lianxh.cn/news/6746f13615db5.html 目录 1. 问题描述 2. 解决方法 3. 哪种方法好? 4. 总结 5. 参考资料 附: 伍德里 ...

  2. stata psm命令_互助问答第301期:关于面板数据的PSM问题

    关于面板数据的PSM问题 老师: 您好!我在微信公众号上看到了互助问答第289期的详细解答,您在其中建议可找工具变量并指出方法服务研究而非指导研究这一观点,让我收益颇多,谢谢您!这里我还想再追加问一些 ...

  3. mysql使用psm登录_倾向匹配得分教程(附PSM操作应用、平衡性检验、共同取值范围、​核密度函数图)...

    原标题:倾向匹配得分教程(附PSM操作应用.平衡性检验.共同取值范围.​核密度函数图) 本文主要包括倾向匹配得分命令简介.语法格式.倾向匹配得分操作步骤 思路,涉及倾向匹配得分应用.平衡性检验.共同取 ...

  4. mysql psm 编程_【SQL】持久性存储模块PSM

    1. 创建PSM函数和过程 创建过程: CREATE PROCEDURE 名字 (参数) 局部声明: 过程体: 创建函数: CREATE FUNCTION 名字 (参数) RETURNS 类型 局部声 ...

  5. stata 求输出相关系数矩阵命令_一文读懂结果输出命令大全(上)

    目录 描述统计量 help tabstat   //Stata 官方命令 描述统计量组间均值差异检验 help ttest help ttable2 help estout 相关分析命令 help p ...

  6. r语言 面板数据回归_R语言——伍德里奇计量经济导论案例实践 第十三章 横截面与面板数据(一)...

    哈喽,停更了大概有三周的计量笔记又要重新开始啦!虽然美国的疫情没有停歇的迹象,可是依旧阻挡不了大学开学的热情.从8月3号开始上课到现在,也经历了很多事情,每天都是抱着死猪不怕开水烫的心情,暗地里安慰自 ...

  7. stata代码命令全集:跟检验do文件、stata常用命令、代码大合集、面板熵值法

     一.常用模型代码整理 1.数据来源: 2.时间跨度:无 3.区域范围:无 4.指标说明: 包含如下模型代码: l OLS模型 l Heckman两阶段模型 l PSM+DID模型 l 固定效应模型( ...

  8. r语言找不到cochrane函数_R语言——伍德里奇计量经济导论案例实践 第十二章 时间序列的序列相关和异方差问题...

    在上一章节的复习笔记中,我们介绍了时间序列比较常见的AR模型和随机游走序列.在对时间序列进行回归时,我们和横截面数据一样做了很多假设,但是上一章内容没有回答如何解决误差项之间的序列相关性 (seria ...

  9. 不用公钥批量部署机器执行命令_模版

    批量部署机器执行命令_小模版 案例: 脚本目的:两台以上机器(ip:172.16.1.187和172.16.1.188)去拷贝主控制机器IP:172.16.1.199上目录/liang/下的ceshi ...

最新文章

  1. java和python的比较-java和python的比较
  2. python的try和except_python的try...except
  3. Oracle将NetBeans交给了Apache基金会
  4. 利用 Arthas 解决启动 StandbyNameNode 加载 EditLog 慢的问题
  5. python 3.6.5 shell_Linux 安装 Python3.6.5
  6. apk获取服务器时间文件名,如何根据APK文件获取应用程序签名时间
  7. mysql 数据库缓冲池_MySQL5.6新特性快速预热Buffer_Pool缓冲池
  8. jsf用于页面判断的标签_JSF –在JSF视图页面中添加标签,图像,按钮和文本字段
  9. 京东面试官:SQL 语句中 left join 后用 on 还是 where,区别大了!
  10. python高中题_python练习题
  11. 基于SSM的课设管理小程序源码(课程设计源码)
  12. Windows设置防火墙允许指定应用正常使用网络
  13. 方正平台(企业级应用的开发平台)
  14. 网络:CGI程序制作
  15. 分享20个增长黑客经典案例。
  16. 各种IT学习视频和资料
  17. Residual Attention: A Simple but Effective Method for Multi-Label Recognition论文阅读笔记
  18. Android客户端登录注册模块
  19. CUTEFTP 权限的修改 之CuteFTP问题 修复CUTEFTP unable to transfer
  20. Unity 图片拼接中间有空隙问题详解

热门文章

  1. 聚集索引扫描97%_聚集前1%:R中的资产分析
  2. Educational Codeforces Round 143 (Rated for Div. 2) 感想
  3. hydra密码破解工具
  4. YubiKey USB安全密钥也出现臭虫可免费换新
  5. 第五十九课 Hadoop入门介绍
  6. 学会线性表,一篇就够了
  7. JS中this的指向
  8. uniapp之h5公众号分享和授权
  9. 使用阿里云OSS实现文件的上传、下载、删除及修改功能
  10. 中华活页文选杂志中华活页文选杂志社中华活页文选编辑部2023年第12期目录