提要
相信《小蝌蚪找妈妈》是不少人的童年回忆。在数据处理中,我们常常需要处理像“小蝌蚪”要找到"妈妈"的数据,并将它们成功匹配。因此,本文将通过一个小例子来讲讲利用stata数据处理中"小蝌蚪"找到"妈妈"的故事。
问题描述
现在工作人员需要处理如下的面板数据
Data:
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
为其邻居一neighbor1
的id
,nb2
为其邻居二neighbor2
的编号,以第一个样本为例,其nb1=2
,nb2=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
那么接下来,将通过这个例子,来介绍让数据迅速匹配的Merge和Rangestat函数
解决方法
方法1:公式求解
从原始的数据中,我们可以将原始的数据按id
,year
来排序,之后通过通过nb1
的值,构造出对应公式,找出数组中的下标,从而代入完成匹配。代码如下
sort id year //排序
by id: gen n = _n //按id生成序列,即1,2,3分别代表不同的年份
local N = n[_N] //生成暂元,记录固定的N=3
gen x_nb1 = x[(nb1 - 1) * `N' + n] //匹配nb1的数据
gen x_nb2 = x[(nb2 - 1) * `N' + n] //匹配nb2的数据
drop n
该方法的关键之处就是构造出了(nb1-1)N+n
这个公式,来计算下标,因为排序过后,x
是一个按id
和year
的序列,只要代入下标,就能得到对应的值。如当nb1=3
时,那么我们就要取x中的第7位到第9位,(nb1-1)*3
得到6,再分别加序列1,2,3
即得到我们想要的结果
方法2:Merge匹配
通常我们在匹配数据时,我们可能会想到Excel中万能的VLOOKUP
函数:
VLOOKUP(要查找的值,查找范围,返回值的位置,精确匹配)
其实,stata
中的Merge函数也能实现该功能。
- Merge函数在stata中常用来进行数据集的合并,即从外部数据文件中,增加变量,它主要有四种方式来进行合并:
-
1:1合并
merge 1:1 varlist using filename [, options]
-
m:1合并
merge m:1 varlist using filename [, options]
-
1:m合并
merge 1:m varlist using filename [, options]
-
m:m合并
merge m:m varlist using filename [, options]
其中
varlist
则是用来识别的变量。
那么以我们这个数据为例,可以将nb1、nb2
对应的数据单独导出数据集,再通过Merge函数,通过id
和year
来识别变量,从而将nb1
和nb2
的数值对应横向合并到原有数据集中。
* 保存nb1的数据集
keep id year x
rename (id x) (nb1 x_nb1)
save "nb1.dta", replace
* 保存nb1的数据集
use "main.dta", clear
keep id year x
rename (id x) (nb2 x_nb2)
save "nb2.dta", replace
* 回到原始的数据集main.dta,进行横向合并
use "main.dta", 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)
这是通过Merge的实现方法,更为具体的功能可以help merge深入了解。
方法3:Rangestat
Rangestat函数,常利用在选定范围内的观察值,来进行相关的统计工作,格式如下:
rangestat (stat) varname, interval(keyvar low high)[options]
(stat)
:常常是你所要进行的统计工作,如求最小值min,求均值mean等等
varname
:即是所进行统计的变量
interval()
:则是选定数据的范围
如下例子,则可以对rep78
筛选后的数据,统计price
、mpg
变量最小值、均值
sysuse auto, clear
rangestat (min) price mpg (mean) price mpg, interval(rep78 0 0)
由于我们的数据是面板数据,其中要通过id
、year
两个变量来确定样本,而rangestat筛选条件只有一个,因此,我们可以通过创建一个新变量来包含上述id
、year
的信息。
在这里,类似于创建我们的学号,如15353333,15代表入学年份,35代表院系,3333代表学生顺序,创建了12000、12001等变量。
gen double bigid= id*10000+year
gen double idyear=nb1*10000+year
在将创建完新的变量之后,我们需要将idyear
和bigid
进行匹配,将那些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 + year
replace idyear = 0 if mi(idyear)
rangestat (min) nb_2=x, interval(bigid idyear idyear)
list, sepby(id)
总结
在这个例子中,我们成功利用Merge
和Rangestat
函数为"小蝌蚪"数据们找到了"妈妈",在过程中,探讨了如何创建新的变量来整合面板数据的id、year
等变量的信息,这些对我们在日后的数据处理中将大有帮助。