Stata连享会 主页 || 视频 || 推文 || 知乎 || Bilibili 站
温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。
New!
lianxh
命令发布了:
随时搜索推文、Stata 资源。安装:
. ssc install lianxh
详情参见帮助文件 (有惊喜):
. help lianxh
连享会新命令:cnssc
,ihelp
,rdbalance
,gitee
,installpkg
⛳ Stata 系列推文:
作者:徐嘉树 (中国人民大学)
邮箱:jiashuxu@ruc.edu.cn
编者按:本文主要摘译自下文,特此致谢!
Source:Fun with frames -Link-
目录
本文编译自 Stata Blog,作者 Chuck Huber 向我们展示了 frames 功能的具体应用。尽管很多用户相当喜欢 frames 功能,但是本文作者一开始对于 Stata 16 中这一新添功能并不感冒,直到他有一次同时需要处理 23 个数据集时,才体会到 frames 功能的好处所在。
在原文中,作者用包含病人信息、医院信息和染色体遗传信息的多个研究数据集,来展示怎样使用 frames 功能。遗憾的是,作者使用的部分研究数据并非开放数据。因此,我们在编译过程中参考了原文的思路和指令,但采用其他来源的数据进行操作,因此输出结果不尽相同。
接下来将从以下五个方面介绍 frames 功能:
frval
的连接;frget
的连接;
首先,我们利用 frame create
命令语句创建名为 patients1 的 frame,并调用名为 patients1 的数据集。
. frame create patients1
. frame patients1: use patients1
接着,继续创建另一个 frame,将它称之为 patients2,也是调用同名的数据集。
. frame create patients2
. frame patients2: use patients2
我们可以用 frame dir
来识别出存储中现有的三个数据框,第一个是 default,另外两个是我们刚刚创建的。我们还能直观地看到每个数据框中包含的数据集、样本量、变量数。
. frame dir
default 0 x 0
patients1 1772 x 14; patients1.dta
patients2 1024 x 14; patients2.dta
现在我们可以利用 frame
前缀拟合一个线性回归模型,再用同样的指令拟合另一个数据集中同样的模型,并分别用 estimate store
将系数保存下来。
. frame patients1: regress sbp c.age##c.bmi
. estimates store patients1
. frame patients2: regress sbp c.age##c.bmi
. estimates store patients2
然后直接用 estimates table
进行两个数据集运行模型的结果对比。
. estimates table patients1 patients2
----------------------------------------
Variable | patients1 patients2
-------------+--------------------------
age | .9977217 .97277459
bmi | 1.8253391 2.1873918
|
c.age#c.bmi | -.01331291 -.01813435
|
_cons | 51.727175 48.077782
----------------------------------------
在拟合模型之后,利用 margins
来估计并将预测值 predictions 保存在一个数据集中,之后利用 graph twoway contour
来绘图。以往我们的做法是关掉正在运行的数据集,重新打开 predictions 数据集。但是现在我们可以轻松地创建一个 frame 来加入 predictions 数据集。
. frame change patients1
. regress sbp c.age##c.bmi
Source | SS df MS Number of obs = 1,764
-------------+---------------------------------- F(3, 1760) = 10.91
Model | 66463.5776 3 22154.5259 Prob > F = 0.0000
Residual | 3574716.18 1,760 2031.08874 R-squared = 0.0183
-------------+---------------------------------- Adj R-squared = 0.0166
Total | 3641179.76 1,763 2065.33169 Root MSE = 45.068
------------------------------------------------------------------------------
sbp | Coef. Std. Err. t P>|t| [95% Conf. Interval]
-------------+----------------------------------------------------------------
age | .9977217 .9175058 1.09 0.277 -.8017941 2.797237
bmi | 1.825339 2.094022 0.87 0.383 -2.281694 5.932372
c.age#c.bmi | -.0133129 .0383641 -0.35 0.729 -.0885568 .061931
_cons | 51.72718 50.30771 1.03 0.304 -46.94198 150.3963
------------------------------------------------------------------------------
. margins, at(age=(30(10)90) bmi=(10(5)40)) saving(predictions, replace)
使用 frame change
转到 patients1 数据中运行多个指令,我们先拟合模型,然后利用 margins
获得预测值。请注意下面这行指令的后面加了选项 saving (predictions, replace)
,意味着我们将预测值保存在了名为 predictions 的数据集中。
我们创建一个名为 contour 的新的数据框,转到 contour 之后调用 predictions 数据集。
. frame create contour
. frame change contour
. use predictions
这个数据集中的三个变量 _at1、_at2、_margin,分别表示年龄、身体质量指数 BMI (Body Mass Index) 和线性回归的预测。
. describe _at1 _at2 _margin
storage display value
variable name type format label variable label
-------------------------------------------------------------------------------
_at1 byte %9.0g age
_at2 byte %9.0g bmi
_margin float %9.0g Linear prediction, predict()
. list _at1 _at2 _margin in 1/5
+------------------------+
| _at1 _at2 _margin |
|------------------------|
1. | 30 10 95.91834 |
2. | 30 15 103.0481 |
3. | 30 20 110.1779 |
4. | 30 25 117.3076 |
5. | 30 30 124.4374 |
+------------------------+
我们对变量重新命名后,绘制一个根据年龄和身体质量指数预测舒张压 SBP (Systolic Blood Pressure) 的等高线图。
. rename _at1 age
. rename _at2 bmi
. rename _margin pr_sbp
. twoway (contour pr_sbp bmi age, ccuts(90(10)170)), ///
> xlabel(30(10)90) ylabel(10(5)40, angle(horizontal)) ///
> xtitle("Age (years)") ///
> ytitle("BMI") ///
> ztitle("Predicted Systolic Blood Pressure") ///
> title("Predicted SBP by Age and BMI")
我们可以使用 frlink
来连接两个数据框。创建名为 community 的 frame,并调用同名数据集 community。
. frame create community
. frame change community
. use community
. list cid cominc in 1/5, abbrev(10)
+---------------+
| cid cominc |
|---------------|
1. | 1 1.0e+04 |
2. | 2 5.0e+04 |
3. | 3 5.0e+04 |
4. | 4 1.2e+04 |
5. | 5 9.0e+03 |
+---------------+
这个 community 数据中包含表示社区编号的变量 cid 和表示过去一年社区人均净收入的变量 cominc。前面使用过的 patients1 数据中则包含表示个人年收入的变量 perinc,也包含表示个人属于哪个社区的变量 cid。
. frame change patients1
. list pid cid perinc in 1/5, abbrev(10)
+---------------------+
| pid cid perinc |
|---------------------|
1. | 1 326 2.0e+04 |
2. | 2 326 1.3e+04 |
3. | 3 325 276 |
4. | 4 325 7200 |
5. | 5 325 2.4e+04 |
+---------------------+
我们使用 frlink
将 patients1 和 community 两个数据框连接起来。因为每个 cid 在 patient1 数据框中出现多次,但是在 community 数据框中只出现一次。所以我们可以明确这是多对一的连接,即 frlink m:1
。逗号后面的 frame (community)
说明 frlink
是将 community 数据框连接到当前的 patients1 数据框上。
. frlink m:1 cid, frame(community)
这样一来,我们的数据框就连接在一起了。我们利用 frval ()
来获取当前数据框以外的其他数据框中变量的取值。比如,我们想要计算一下每个受访者个人年收入相对于社区人均净收入的比值。我们可以生成一个名为 rel_inc 的新变量,它表示当前 patient1 数据框中的个人年收入 perinc 除以 community 数据框中社区人均净收入 cominc 得到的比值。利用 frval (community, cominc)
就能够获取 community 数据框中变量 cominc 的值。
. generate rel_inc = perinc / frval(community, cominc)
. list pid cid cominc perinc rel_inc in 1/5, abbrev(16)
+------------------------------------------+
| pid cid cominc perinc rel_inc |
|------------------------------------------|
1. | 1 326 2.8e+03 2.0e+04 7.272727 |
2. | 2 326 2.8e+03 1.3e+04 4.727273 |
3. | 3 325 1.1e+03 276 .2509091 |
4. | 4 325 1.1e+03 7200 6.545455 |
5. | 5 325 1.1e+03 2.4e+04 21.81818 |
+------------------------------------------+
如上表中的第三个人 (pid=3),所在社区编号 325 的人均净收入为 1100 元,而他个人的年收入为 276 元,变量 rel_inc 的取值 0.25,意味着这个人的个人年收入比 325 社区人均净收入低 75%。
另外,我们也可以用 frget
来复制连接在一起的其他 frame 中的变量。举个例子,我们有一个名为 long 的纵向数据集,其中包含追踪受访者三期的数据,即每个受访者有三期的身体质量指数 bmi 和舒张压 sbp 信息。下面让我们来给这个数据创建一个新的同名 frame。
. frame create long
. frame change long
. use long
. list in 1/10, abbrev(10)
+--------------------------------+
| pid j bmi age sbp |
|--------------------------------|
1. | 1 1 19.5325 45 108 |
2. | 1 2 19.5325 45 108 |
3. | 1 3 19.5325 45 110 |
4. | 2 1 22.53906 49 96 |
5. | 2 2 22.53906 49 104 |
|--------------------------------|
6. | 2 3 22.53906 49 108 |
7. | 3 1 25.29938 82 163 |
8. | 3 2 25.29938 82 174 |
9. | 3 3 25.29938 82 182 |
10. | 4 1 24.53125 57 147 |
+--------------------------------+
我们想要利用这三期追踪数据拟合一个多层模型,并调节性别的影响。表示性别的变量 male 保存在数据框 patients1 中,让我们用 frlink
将两个数据框连起来。
. frlink m:1 pid, frame(patients1)
接下来,我们就可以用 frget
来复制变量 male 了,将它从 patients1 数据框中复制到当前 long 数据框。
. frget male, from(patients1)
. list in 1/10, abbrev(10)
+---------------------------------------------------+
| pid j bmi age sbp patients1 male |
|---------------------------------------------------|
1. | 1 1 19.5325 45 108 1 1 |
2. | 1 2 19.5325 45 108 1 1 |
3. | 1 3 19.5325 45 110 1 1 |
4. | 2 1 22.53906 49 96 2 1 |
5. | 2 2 22.53906 49 104 2 1 |
|---------------------------------------------------|
6. | 2 3 22.53906 49 108 2 1 |
7. | 3 1 25.29938 82 163 3 1 |
8. | 3 2 25.29938 82 174 3 1 |
9. | 3 3 25.29938 82 182 3 1 |
10. | 4 1 24.53125 57 147 4 0 |
+---------------------------------------------------+
这样我们就可以拟合多层模型了。
. mixed sbp i.male c.age##c.bmi || pid:, nolog noheader
------------------------------------------------------------------------------
sbp | Coef. Std. Err. z P>|z| [95% Conf. Interval]
-------------+----------------------------------------------------------------
1.male | 2.039036 2.435889 0.84 0.403 -2.735219 6.813291
age | .6067942 .9697704 0.63 0.532 -1.293921 2.507509
bmi | 1.03139 2.212426 0.47 0.641 -3.304886 5.367665
|
c.age#c.bmi | -.0003429 .0405329 -0.01 0.993 -.0797859 .0791002
|
_cons | 72.64936 53.15391 1.37 0.172 -31.5304 176.8291
------------------------------------------------------------------------------
------------------------------------------------------------------------------
Random-effects Parameters | Estimate Std. Err. [95% Conf. Interval]
-----------------------------+------------------------------------------------
pid: Identity |
var(_cons) | 2085.381 76.46401 1940.773 2240.764
-----------------------------+------------------------------------------------
var(Residual) | 545.5202 12.98857 520.6479 571.5807
------------------------------------------------------------------------------
LR test vs. linear model: chibar2(01) = 3875.23 Prob >= chibar2 = 0.0000
开头我们说到过,作者喜欢 frames 的主要原因是一次同时处理 23 个数据集。这次数据处理就是使用了包含 22 条染色体遗传信息的 22 个数据集和病人其他信息的 1 个数据集。这些遗传信息数据集中的每一个数据都很大,大到需要 Stata MP 版本才能打开。
我们平时使用的 Stata 一般是 SE 版本,因为我既没有 MP 版本的软件,也没有作者使用的遗传信息数据,所以这部分的内容没有实际操作,只是解释一下作者的做法。
他在 MP 版本中先是利用 set segmentsize
来分配内存,然后用 set maxvar
将允许的最大变量数从默认值 5000 更改为 80000 ,这样才打开第一个染色体数据集 chromosome1。
打开数据后,利用上文提到的 frlink
和 frget
等功能连接数据框并从其他数据框复制所需变量。之后用 dsregress
拟合出一个因变量为舒张压,含有年龄、性别、身体质量指数等自变量的 Lasso 模型。最重要的是,这个模型中控制了超过七万个表示遗传信息的变量。正是这一点,让作者对 frames 功能大吃一惊。
作者还写了一个循环进一步探索是否还有更大的使用空间,他用 Stata 同时打开了这些数据集中超过 90 万个变量。试着想一想, Stata MP 版本最多同时设置 100 个数据框,也就是说理论上能够同时使用 1200 万个变量,这就是 Stata 16 中 frames 功能能做到的!
Note:产生如下推文列表的 Stata 命令为:
lianxh 合并, m
安装最新版lianxh
命令:
ssc install lianxh, replace
免费公开课
最新课程-直播课
专题 | 嘉宾 | 直播/回看视频 |
---|---|---|
⭐ 最新专题 | 文本分析、机器学习、效率专题、生存分析等 | |
研究设计 | 连玉君 | 我的特斯拉-实证研究设计,-幻灯片- |
面板模型 | 连玉君 | 动态面板模型,-幻灯片- |
面板模型 | 连玉君 | 直击面板数据模型 [免费公开课,2小时] |
⛳ 课程主页
⛳ 课程主页
关于我们
课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法
等
连享会小程序:扫一扫,看推文,看视频……
扫码加入连享会微信群,提问交流更方便
✏ 连享会-常见问题解答:
✨ https://gitee.com/lianxh/Course/wikis
New!
lianxh
和songbl
命令发布了:
随时搜索连享会推文、Stata 资源,安装命令如下:
. ssc install lianxh
使用详情参见帮助文件 (有惊喜):
. help lianxh