06470 1 1 家庭信息 1 232 0 个人信息 2 230 1 个人信息 07470 1 0 家庭信息
1 240 1 个人信息 ... ...
假设家庭记录:第1-5列为家庭代码,第7列为“1”表示家庭信息,第9列为住房类型。
个人记录:第1-5列为个人代码,第7列为“2”表示个人信息,第8-9列为年龄,第11列为性别代码。
现在我们想产生一个Stata数据,包含下列信息:家庭代码、住房类型、个人代码、年龄、性别代码。每个记录只包含一个个人信息,并且来自同一家庭的个人家庭信息相同。
如果原始数据中个人记录中也有家庭代码信息,则可以分别将家庭信息和个人信息读入系统,建立两个数据文件,然后根据家庭代码多对一合并数据即可。但原始记录中个人记录中没有家庭代码,这里需要我们自己构造一个新的家庭代码。
首先,根据数据结构,建立两个数据字典文件famliy.dct和person.dct,分别如下: *BEGIN family.dct dictionary using hier.raw { _column(7) byte _column(9) byte } *END family.dct *BEGIN person.dct dictionary using hier.raw { _column(7) byte _column(8) byte _column(11) byte } *END person.dct long rectype dwell famid _ \\\long rectype age sex perid / _ \\\\ 首先检验一下字典是否能够正确的将数据导入系统 clear
infile using family if rectype==1 in 1/100 list in 1/5 type hier.raw clear
infile using person if rectype==2 in 1/100 list in 1/5 type hier.raw
如果不存在什么问题,上述语句修改后,可以放在do文件里面。
41
基本的do文件安排是首先读入家庭信息,产生家庭数据,然后 读入个人信息,产生个人数据,最后将家庭数据和个人数据合并。为了实现第三步的合并,这里我们需要产生一个识别代码。首先,第一步, clear
infile using family if rectype==1 gen long id=_n /*产生一个识别码*/ sort id
save tmph, replace
然后,我们读入个人数据,不过,我们会将原始数据中家庭信息作为个人信息一样读入系统,读入后数据如下:
+-----------------------------+ | perid rectype age sex | |-----------------------------|
1. | 6470 1 1 . | 家庭信息 2. | 1 2 32 0 | 3. | 2 2 30 1 |
4. | 7470 1 0 . | 家庭信息 5. | 1 2 40 1 |
我们利用gen id=1 if rectype==1产生一个代码全是1 的变量,结果如下: +----------------------------------+ | perid rectype age sex id | |----------------------------------| 1. | 6470 1 1 . 1 | 2. | 1 2 32 0 . | 3. | 2 2 30 1 . | 4. | 7470 1 0 . 1 | 5. | 1 2 40 1 . |
然后,利用replace id=sum(id),产生如下结果: +----------------------------------+ | perid rectype age sex id | |----------------------------------| 1. | 6470 1 1 . 1 | 2. | 1 2 32 0 1 | 3. | 2 2 30 1 1 | 4. | 7470 1 0 . 2 | 5. | 1 2 40 1 2 |
最后,将类型为家庭信息的记录删除drop if rectype==1,则仅剩下个人信息的记录,并且个人记录里包含了家庭记录的识别代码id。将个人数据与家庭数据按照id进行合并即可。 最终程序如下:
42
*BEGIN crhier.do capture log close log using crhier, replace set more off clear infile using family if rectype==1 drop rectype gen long id=_n sort id save tmph, replace clear infile using person assert rectype==1 |rectype==2 gen long id=1 if rectype==1 replace id=sum(id) drop if rectype==1 drop rectype sort id perid merge m:1 id using tmph assert _merge==3 drop _merge id sort famid perid save hier, replace erase tmph.dta log close exit *END crhier.do 关于assert
assert 命令可以用来检验变量取值是否存在问题,当assert后面的条件成立时,Stata不会有任何提示,如果条件不成立,将给出提示,如果在do文件中,do文件将停止执行。 可复制性
程序中避免随机因素的存在,否则每次运行do文件可能会产生不同结果。可以利用set seed,比如如果使用的数据比较大,在初步试分析中可以利用sample 命令抽取一个较小的样本进行分析,sample命令抽象时是随机的,所以为了保证每次运行获得的结果一致,可以使用set seed #保证抽得的样本一样。在进行随机模拟和bootrap里,也经常需要加上set seed。
另外,有时仅有set seed 也不能保证不确定性的发生。比如sort命令, sort region
将观测按地区进行排序,但在同一区域内观测的排序是随机的,为了保证每次运行得到同样的结果,可以排序时加上stable参数,即 sort region, stable
43
4、_n和_N的用法
generate y=x[_n] 和
generate y=x 作用是一样的。 generate y=x[_n-1]
则y为x的滞后变量,其中y[1]为缺失值。 generate y=x[_n+1]
y为x的先导变量,y[_N]为缺失值 generate y=x[_N]
y的所有观测值均为x[_N] generate y=x[_N-_n+1] y是x逆序观测值
by varlist: stata_cmd
结果和按照varlist分组生成不同的数据,然后再分别对不同数据运行stata_cmd的作用一样。 by famid: gen persons=_N by famid: gen persons=_N if _n==1 summarize persons
附录:hier.raw BEGIN hier.raw CUT HERE 06470 1 1 44
1 232 0 2 230 1 07470 1 0 1 240 1 08470 1 0 1 227 0 09470 1 0 1 213 1 2 222 0 3 224 1 10470 1 1 1 220 0 2 211 1 11470 1 0 1 217 0 2 210 1 3 226 1 12470 1 0 1 218 1 2 220 0 13470 1 0 1 217 1 14470 1 0 1 215 1 2 218 0 15470 1 0 1 213 0 2 229 0 16470 1 0 1 219 1 19470 1 1 1 215 0 2 219 1 24470 1 0 1 222 1 26470 1 0 1 211 1 2 221 1 37470 1 0 1 215 0 2 218 0 3 221 1 4 222 0 5 240 1 39920 1 0 1 235 1 2 218 0 39925 1 1 1 213 0 2 229 0 46470 1 1 1 279 1
45