Stata:generate 函数、if 表达式与常用 egen 函数汇总
欢迎各位培训班会员参加明晚的第 4 次直播课:「函数、宏、标量和矩阵(一)」。
因为上次课程的内容没有讲完,明晚我们会继续讲解 generate 函数、if 表达式和常用 egen 函数汇总的内容。
该课程是「Stata 编程导论的第 3 课时」,课程主页(点击文末的阅读原文即可跳转):
https://rstata.duanshu.com/#/brief/course/57571646805e4786b622867cfd5ad1d9
本次课及下面的几讲内容将集中于 Do 文档的编程。这节课我们将讲解 Do 文档编程中的一些基础概念:函数、宏、标量和矩阵。
一些编程的细节
本节我们将使用 census2c 数据集:
clear all
*- 一些编程的细节
use census2c, clear
list, sep(0)
*> +---------------------------------------------------------------------+
*> | state region pop popurb medage marr divr |
*> |---------------------------------------------------------------------|
*> 1. | Connecticut NE 3107.6 2449.8 32.00 26.0 13.5 |
*> 2. | Illinois N Cntrl 11426.5 9518.0 29.90 109.8 51.0 |
*> 3. | Indiana N Cntrl 5490.2 3525.3 29.20 57.9 40.0 |
*> 4. | Iowa N Cntrl 2913.8 1708.2 30.00 27.5 11.9 |
*> 5. | Kansas N Cntrl 2363.7 1575.9 30.10 24.8 13.4 |
*> 6. | Maine NE 1124.7 534.1 30.40 12.0 6.2 |
*> 7. | Massachusetts NE 5737.0 4808.3 31.20 46.3 17.9 |
*> 8. | Michigan N Cntrl 9262.1 6551.6 28.80 86.9 45.0 |
*> 9. | Minnesota N Cntrl 4076.0 2725.2 29.20 37.6 15.4 |
*> 10. | Missouri N Cntrl 4916.7 3349.6 30.90 54.6 27.6 |
*> 11. | Nebraska N Cntrl 1569.8 987.9 29.70 14.2 6.4 |
*> 12. | New Hampshire NE 920.6 480.3 30.10 9.3 5.3 |
*> 13. | New Jersey NE 7364.8 6557.4 32.20 55.8 27.8 |
*> 14. | New York NE 17558.1 14858.1 31.90 144.5 62.0 |
*> 15. | N. Dakota N Cntrl 652.7 318.3 28.30 6.1 2.1 |
*> 16. | Ohio N Cntrl 10797.6 7918.3 29.90 99.8 58.8 |
*> 17. | Pennsylvania NE 11863.9 8220.9 32.10 93.7 34.9 |
*> 18. | Rhode Island NE 947.2 824.0 31.80 7.5 3.6 |
*> 19. | S. Dakota N Cntrl 690.8 320.8 28.90 8.8 2.8 |
*> 20. | Vermont NE 511.5 172.7 29.40 5.2 2.6 |
*> 21. | Wisconsin N Cntrl 4705.8 3020.7 29.40 41.1 17.5 |
*> +---------------------------------------------------------------------+
Stata 中的数据集也是表式的,表的每一行我们称为观测值,每一列我们称为变量。从上面的结果中我们可以看到,census2c.dta 数据集一共有 21 个观测值和 7 个变量。
Stata 数据集中的变量名称必须是互不相同的,同时还要遵守下面的规则:
不能包含空格; 不能包含运算符,例如 -
,+
,*
,/
;不能包含 .
,?
;不能以数字开头; 大小写敏感; 其它暂时没想起来的。
建议不要使用中文变量名,变量名不宜使用 a, b, c 这种缺乏实际含义的字符,可以使用简单的英文或英文缩写。例如 pop 之类的。
变量列表
help varlist
很多 Stata 命令可以处理不止一个变量,也就是可以接受变量列表,例如:
sum pop - divr
*> Variable | Obs Mean Std. dev. Min Max
*> -------------+---------------------------------------------------------
*> pop | 21 5142.903 4675.152 511.456 17558.07
*> popurb | 21 3829.776 3851.458 172.735 14858.07
*> medage | 21 30.25714 1.199821 28.3 32.2
*> marr | 21 46.16905 39.9059 5.226 144.518
*> divr | 21 22.17948 19.31113 2.142 61.972
sum pop*
*> Variable | Obs Mean Std. dev. Min Max
*> -------------+---------------------------------------------------------
*> pop | 21 5142.903 4675.152 511.456 17558.07
*> popurb | 21 3829.776 3851.458 172.735 14858.07
sum *r
*> Variable | Obs Mean Std. dev. Min Max
*> -------------+---------------------------------------------------------
*> marr | 21 46.16905 39.9059 5.226 144.518
*> divr | 21 22.17948 19.31113 2.142 61.972
sum pop popurb
sysuse auto, clear
reg price mpg - for
*> Source | SS df MS Number of obs = 69
*> -------------+---------------------------------- F(10, 58) = 8.66
*> Model | 345416162 10 34541616.2 Prob > F = 0.0000
*> Residual | 231380797 58 3989324.09 R-squared = 0.5989
*> -------------+---------------------------------- Adj R-squared = 0.5297
*> Total | 576796959 68 8482308.22 Root MSE = 1997.3
*>
*> ------------------------------------------------------------------------------
*> price | Coefficient Std. err. t P>|t| [95% conf. interval]
*> -------------+----------------------------------------------------------------
*> mpg | -21.80518 77.3599 -0.28 0.779 -176.6578 133.0475
*> rep78 | 184.7935 331.7921 0.56 0.580 -479.3606 848.9476
*> headroom | -635.4921 383.0243 -1.66 0.102 -1402.198 131.2142
*> trunk | 71.49929 95.05012 0.75 0.455 -118.7642 261.7628
*> weight | 4.521161 1.411926 3.20 0.002 1.694884 7.347438
*> length | -76.49101 40.40303 -1.89 0.063 -157.3665 4.38444
*> turn | -114.2777 123.5374 -0.93 0.359 -361.5646 133.0092
*> displacement | 11.54012 8.378315 1.38 0.174 -5.230896 28.31115
*> gear_ratio | -318.6479 1124.34 -0.28 0.778 -2569.259 1931.964
*> foreign | 3334.848 957.2253 3.48 0.001 1418.754 5250.943
*> _cons | 9789.494 6710.193 1.46 0.150 -3642.416 23221.4
*> ------------------------------------------------------------------------------
foreach i of varlist _all{
di "`i'"
}
foreach i of varlist make price{
list `i' in 1
}
tostring make price, replace
tostring _all, replace
destring _all, replace
数值列表
help numlist
数值列表的用途也很广泛:
forval i = 1/10{
di "`i'"
di `i' + 1
}
forval i = 1(2)10{
di "`i'"
}
forval i = 10(-2)1{
di "`i'"
}
forval i = 10 15 to 30{
di "`i'"
}
foreach i in 1 2 3 4 5{
di "`i'"
}
sysuse uslifeexp, clear
line le_wm year, yla(0 20(10)80)
if / in
help if
help in
很多 Stata 命令可以使用 if 或者 in 进行观测值筛选:
use census2c, clear
list state pop medage if medage >= 32
reg pop medage if medage >= 30
*> Source | SS df MS Number of obs = 11
*> -------------+---------------------------------- F(1, 9) = 4.42
*> Model | 89780675.1 1 89780675.1 Prob > F = 0.0649
*> Residual | 182823809 9 20313756.6 R-squared = 0.3293
*> -------------+---------------------------------- Adj R-squared = 0.2548
*> Total | 272604484 10 27260448.4 Root MSE = 4507.1
*>
*> ------------------------------------------------------------------------------
*> pop | Coefficient Std. err. t P>|t| [95% conf. interval]
*> -------------+----------------------------------------------------------------
*> medage | 3378.154 1606.879 2.10 0.065 -256.8585 7013.166
*> _cons | -99897.76 50080.02 -1.99 0.077 -213186.6 13391.12
*> ------------------------------------------------------------------------------
list state pop in 1/5
reg pop medage in 1/10
keep in 1/10
*- help programming functions
list if inrange(medage, 30, 32)
list if inlist(state, "Connecticut", "Illinois")
缺失数据的处理
help missing
Stata 中有 27 中数值型缺失值。
.
是默认的数值缺失值,也被称为系统缺失值,.a, .b, .c, ..., .z
则被称为拓展缺失值。这些缺失值和非缺失值的大小关系是:
list if age > 60 & age < .
list if age >= .
drop if missing(divr)
drop if missing(divr, marr)
字符串型缺失值是 ""
括起来的空值。
一些 Stata 命令可以在运算的时候自动处理缺失值,而处理的通常方式是删除缺失值。
clear
input x1 x2 x3 x4
1 2 . 4
4 5 .a 4
6 . .b 5
7 18 .c 9
end
egen min = min(x3) // 忽略了缺失值
egen max = max(x2) // 忽略了缺失值
egen rowmax = rowmax(x1 x2 x3) // 忽略了缺失值
correlate x1 x2 x4 // 忽略含缺失值的观测值
correlate x1 x2 x4 if !missing(x2)
pwcorr x1 x2 x4 // 利用所有的成对数据
pwcorr x1 x2 x4 if !missing(x2)
数值型变量的缺失值可以使用 mvdecode 或者 mvencode 处理:
mvencode x2, mv(. = 0)
mvencode x3, mv(. = 1 \ .a = 2)
mvdecode x2, mv(18)
mvdecode x2, mv(2 = . \ 5 = .a)
字符型变量转数值型变量
gen id = _n
gen idstr = string(id)
gen idnum = real(idstr)
gen statestr = real(state)
destring _all, replace
tostring _all, replace
encode state, gen(statenum)
decode region, gen(regionstr)
use census2c, clear
gen pop3 = strofreal(pop, "%6.3f")
gen pop4 = string(pop, "%6.3f")
tostring pop, gen(pop5)
clear all
set obs 10
gen date = _n
tostring date, format(%tdCY-N-D) replace
gen date2 = string(date, "%tdCY-N-D")
还有一个需要注意的是带引号的字符串。我们可以使用绝对引号括起来:
di `""Hello""'
di "Hello"
di "1+2"
di "`=date2[1]'"
di `""`=date2[1]'""'
di "`=1+2'"
generate 函数
use census2c, clear
gen urbanized = popurb / pop
sum urbanized
replace urbanized = 100 * urbanized
sum urbanized
gen newengland = inlist(state, "Connecticut", "Maine", ///
"Massachusetts", "New Hampshire", "Rhode Island", "Vermont")
gsort newengland
list state medage pop if newengland, sep(0)
list state medage pop if inrange(pop, 5000, 9999), sep(0)
replace divr = int(divr)
gen divrmod = mod(divr, 2)
gen stateC = substr(state, 1, 1)
keep pop
gen popsum = sum(pop)
egen poptotal = total(pop)
if 表达式和示性变量
示性变量又被称为指示变量、虚拟变量、零一变量、逻辑变量。
use census2c, clear
gen smallpop = 0
replace smallpop = 1 if pop <= 5000 & !missing(pop)
gen largepop = 0
replace largepop = 1 if pop > 5000 & !missing(pop)
list state pop smallpop largepop, sep(0)
示性变量也可以参与计算,例如:
sysuse auto, clear
gen wt = 10 * (rep78 == 1) + 20 * (rep78 == 2) + 30 * (rep78 == 3)
cond() 函数
use census2c, clear
gen netmarr2x = cond(marr/divr > 2.0, 1, 2)
label def netmarr2xc 1 "marr > 2 divr" 2 "marr <= 2 divr"
label val netmarr2x netmarr2xc
tabstat pop medage, by(netmarr2x)
连续变量与离散变量之间的转换
use census2c, clear
gen medagebrack = recode(medage, 29, 30, 31, 32, 33) // 包括右边不包括左边
tab medagebrack
gen size = irecode(pop, 1000, 4000, 8000, 20000)
label def popsize 0 "<1m" 1 "1-4m" 2 "4-8m" 3 ">8m"
label val size popsize
tabstat pop, stat(mean min max) by(size)
help pctile
use census2c, clear
xtile medagequart = medage, nq(4)
tabstat medage, stat(n mean min max) by(medagequart)
*- 计算分位数并存储起来
use census2c, clear
_pctile medage, nq(4)
ret list
egen 函数
egen 函数太多了,有很多非常好用的,我这里列举一些:
egen 与常见统计量
clear
set obs 10
*- 生成1-10的连续序列
gen A = _n
*- 生成总的观测值数
gen num = _N
*- 得到变量A的均值
egen avg = mean(A)
egen med = median(A)
egen std = sd(A)
egen min = min(A)
egen max = max(A)
egen 参与分组和排序
clear
set obs 10
gen A = _n
gen num = _N
*- 根据奇偶数分组,偶数为0,奇数为1
gen se = mod(A, 2)
*- 根据奇偶数分组,A只参与排序,不参与分组求分组后组列总和
bysort se(A): egen sum = sum(A)
bysort se: egen sum0 = sum(A)
*- A既参与分组也参与排序,求分组后的组总和
bysort se A : egen sum1 = sum(A)
*- 根据奇偶数分组,求分组后的组列累计和
bysort se(A): gen sum2 = sum(A)
sort se
list A se sum sum1 sum2
egen 与 seq
两者搭配可以生成有规律的连续序列:
clear
set obs 10
gen a1 = _n
*- 生成 1 - 10
egen a2 = seq()
*- 生成 1 - 10
range a3 1 _N
*- 根据奇偶数分组
gen se = mod(a1, 2)
*- 根据奇偶数分组之后,连续序列中的每个数字重复两次
bysort se(a1): egen b = seq(), block(2)
*- a1 也参与分组
bysort se a1 : egen b1= seq(), block(2)
*- 分组之后,变量 c 的序列从 3 到 1 递减并循环
bysort se(a1): egen c = seq(), from(3) to(1)
*- 分组之后,变量 d 从 1 到 3 循环
bysort se(a1): egen d = seq(), to(3)
egen 与 fill
egen 与 fill()搭配也可以生成一串规律的序列,在某些情况下,fill 与 seq 起到的效果是一样的,不同点在于 seq 的步长只能为 1,而 fill 可以自己设定步长:
clear
set obs 10
*- 按 1、3、5 的规律填充
egen a = fill(1 3 5)
*- 按 1、2 的规律填充
egen b = fill(1 2)
*- 从 6 开始到 3,步长为 -3
egen c = fill(6(-3)3)
*- 按1、1、2、2的规律填充
egen d = fill(1 1 2 2)
*- 按 1、1、2、1、1、2 的规律填充
egen e = fill(1 1 2 1 1 2)
egen f = fill(-3(3)6 -3(3)6)
egen g = fill(10 20 to 50 10 20 to 50)
fill 不能与 bysort 结合使用!
egen 与 diff
egen 与 diff 搭配时,若 varlist 中的变量值都相同,则给 diff 赋值为 0,否则为 1:
clear
use egenxmpl3, clear
egen differ = diff(inc*)
egen 与 row 函数
clear
use egenxmpl4, clear
*- rowtotal()、rowmean() 和 rowsd()函数会忽略缺失值
egen total = rowtotal(a b c)
egen avg = rowmean(a b c)
egen std = rowsd(a b c)
*- 得到缺失值的个数
egen miss = rowmiss(a b c)
*- 最小值
egen min = rmin(a b c)
*- 得到该行最后一个变量值(缺失值不计入)
egen last = rlast(a b c)
egen 与 pc、pctile
sysuse auto, clear
keep mpg
*- 得到列总和
egen sum = sum(mpg)
*- 得到每个观测值占列总和的比例(小数)
egen per = pc(mpg), prop
*- 百分数
egen per_1 = pc(mpg)
*- 得到 mpg 的 0.25 分位数
egen pct = pctile(mpg), p(25)
*- 中位数
egen pct_1 = pctile(mpg)
egen 与 rank
sysuse auto, clear
keep in 16/30
keep mpg
*- 正序无并列排名
egen rank_u = rank(mpg), unique
*- 正序排名,排名可能会出现0.5
egen rank = rank(mpg)
*- 倒序排名
egen rank_r = rank(-mpg)
*- 指定最小观测值排名为1,若出现相同数字,并列排名
egen rank_t = rank(mpg), track
*- 指定最大观测值排名为1,若出现相同数字,并列排名
egen rank_f = rank(mpg), field
egen 与 anyvalue、anymatch
sysuse auto, clear
keep rep78
*- 若rep78不为3、4、5,则为缺失值
egen a = anyvalue(rep78), v(3/5)
*- 若rep78不为3、4、5,则赋值为0,否则为1
egen b = anymatch(rep78), v(3/5)
egen 与 std
use states1, clear
*- 将age标准化为均值为0,方差为1的变量
egen stdage = std(age)
sum age stdage
*- 两者的相关系数为1
corr age stdage
*- 生成均值为1(不指定均值时默认为0),标准差为2的变量
egen newage1 = std(age), std(2)
*- 均值为2,标准差为4
egen newage2 = std(age), mean(2) std(4)
egen newage3 = std(age), mean(2)
sum age new*
更多 egen 函数我就不再继续讲解了,布置一个作业:
这些命令是外部命令,我已经把安装包放在了附件中,可以使用下面的命令安装:
例如 _gclsort:
net install _gclsort.pkg, from("_gclsort.pkg 文件所在的文件夹路径(这个路径不包含 _gclsort.pkg 的名字)") force replace
例如在我的电脑上(_gclsort.pkg 文件在 /Users/ac/Documents/ssc/_gclsort/ 文件夹中):
net install _gclsort.pkg, from("/Users/ac/Documents/ssc/_gclsort/") force replace
其他的也都类似。
自我学习:
clsort
*- 使用
clear
input ///
varname1 select
20 0
40 1
15 1
10 1
55 0
60 1
end
egen default = clsort(varname1) if select
egen inplace = clsort(varname1) if select, inplace
peers
*- 使用
sysuse auto, clear
keep weight foreign
egen peers = peers(weight), by(foreign)
gsort foreign
replace weight = . in 1
bysort for: egen mean = mean(weight)
egenmore & egenmisc
help egenmore
help egenmisc
例如:egen + mlabvpos 改变标签的方向减少遮盖:
use allstates, clear
egen clock = mlabvpos(ownhome propval100)
tw sc ownhome propval100, ///
mla(stateab) ///
mlabsize(small) ///
mlabvpos(clock)
gwtmean
*- 使用
sysuse auto, clear
keep rep78 price
egen wtmean = wtmean(price), weight(rep78)
*- 上面的计算结果和下面的结果是一样的
sum price [w=rep78]
搜集更多的 egen 拓展函数。
由于时间关系,今天的内容就先到这里了。谢谢~
直播信息
为了让大家更好的理解上面的内容,欢迎各位培训班会员参加明天晚上 9 点的直播课:「函数、宏、标量和矩阵(一)」
直播地址:腾讯会议(需要报名 RStata 培训班参加) 讲义材料:需要报名 RStata 培训班,详情可阅读:一起来学习 R 语言和 Stata 啦!学习过程中遇到的问题也可以随时提问!
更多关于 RStata 会员的更多信息可添加微信号 r_stata 咨询:
预定纸质版讲义材料
在之前的课程结尾我把讲义材料整理成了一本讲义材料,感兴趣的小伙伴可以联系微信号 r_stata 李老师预定(Stata 编程导论是 55元/本,255 页彩色胶装):
购买长期会员有赠送纸质书哦!