Stata绘图:绘制单个变量的时序图

发布时间:2019-10-02 阅读 130

徐嘉树 (中国人民大学)
jiashuxu@ruc.edu.cn

Source: Chatfield, Mark D. "Graphing each individual's data over time." The Stata Journal 18.3 (2018): 503-516. [PDF]

Stata连享会   主页 || 视频 || 推文

连享会 - Stata 暑期班

线上直播 9 天:2020.7.28-8.7
主讲嘉宾:连玉君 (中山大学) | 江艇 (中国人民大学)
课程主页https://gitee.com/arlionn/PX | 微信版


目录


对于纵向和面板数据,绘制单个个体随时间变化的图表是一种有效的信息探索方式,对多变量随时间变化、以及着重多个时间点的数据尤为突出。仔细研究单个个体的时序图不仅可以洞察数据的性质和质量,为进一步分析提供信息。若选择一些典型,更能够为你的研究展示提供强有力的证据。

Cox (2010) 在讨论数据图形化时,强调了个体之间或个体组之间的比较。我们在探索数据时,绘制每个个体随时间变化的数据(在单独的图表中)可能是一种容易被忽视的做法。从本质上讲,这种方法强调的是个体内部(而非个体之间)的差异。研究一些个体的时序图可以加深我们对数据的理解,并就可能对数据提出哪些研究问题、以及如何分析数据产生一些新的想法。随着时间的推移,数据中有很多关于个人的信息,绘制原始数据图可能是一项相当艰巨的挑战。各种符号和线段可以相互重叠,使我们制成的图形让人难以理解。对此,为单个个体绘制独立的时序图恰恰是一种解决办法。

接下来让我们看一看,在 Stata 中怎样绘制这些时序图。

1. 数据说明

本文将使用美国劳动力市场经验纵向调查 National Longitudinal Survey of Labor Market Experience 中 1968 年 14-26 岁年轻女性的子样本数据进行时序图的绘制。这部分数据包含在 1968 年至 1988 年的 21 年中 (除 1974 年、1976 年、1979 年、1981 年、1984 年和 1986 年外) 受访女性的工资及相关因素随时间变化的信息。我们需要在 Stata 中导入数据,并设定绘图模板。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
. use http://www.stata-press.com/data/r15/nlswork.dta, clear. xtset. xtdescribe. set scheme sj

2. 绘制单变量的单个个体时序图

在第一个简单的例子中,我们打算绘制个体工资随时间变化的时序图。首先,我们需要做一些准备工作,生成工资相关的变量。由于在我们使用的样本中有很多个体 (4711) ,在此我们只选择前六个个体做例子,来绘制六张单个个体的时序图。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
. generate  wage = exp(ln_wage). summarize wage, detail. generate  wage_trunc = min(wage, 20) if !missing(wage). label variable wage_trunc "Wage ($/hour)". keep if idcode <= 6

对于绘制单变量的单个个体时序图,我们可以利用下列指令得到六个个体的时序图,并通过putdocx保存到文档中。其中,我们用scatter绘制散点图,用ylabelyscalexlabelxmtickxscale分别修饰 Y 轴和 X 轴的标签、刻度和范围。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
putdocx clearputdocx begin, landscapeputdocx paragraphlevelsof idcode, local(idcodes) cleanforeach id of local idcodes { scatter wage_trunc year if idcode == `id' , connect(l) sort ///   ylabel(0 2 4 6 8 10 12 14 16 18 20 "≥20", angle(horizontal))  ///   yscale(range(0 20.5))  ///   xlabel(68 "1968" 73 "1973" 78 "1978" 83 "1983" 88 "1988")  ///   xmtick(68 69 70 71 72 73 75 77 78 80 82 83 85 87 88, grid notick)  ///   xscale(range(67.5 88.5))  ///   title("id `id'")  ///   graphregion(color(white))  ///   name(g`id', replace)   graph export "temp_graph.png", replace   putdocx image "temp_graph.png"}putdocx save "Example 1. Individual Graphs.docx", replaceerase "temp_graph.png"

通过以上指令,我们能够得到六张个体时序图,以第五张为例,如下图所示:

图1. 个体工资随时间变化 (idcode == 5)
图1. 个体工资随时间变化 (idcode == 5)

连享会计量方法专题……

3. 绘制多变量的单个个体时序图

接下来的第二个例子较为复杂,我们的时序图将展示这个样本中describe指令所显示的多个变量的情况。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
 use http://www.stata-press.com/data/r15/nlswork, clear generate wage = exp(ln_wage) keep idcode tenure hours union msp race grade age year wage generate death_yr = 83 if idcode==5 // variable created for illustration describe
. describe
Contains data from nlswork.dta obs: 28,534 National Longitudinal Survey. Young Women 14-26 years of age in 1968 vars: 11 27 Nov 2016 08:14 size: 627,748---------------------------------------------------------------------- storage display valuevariable type format label variable label----------------------------------------------------------------------idcode int %8.0g NLS IDyear byte %8.0g interview yearage byte %8.0g age in current yearrace byte %8.0g racelbl racemsp byte %8.0g 1 if married, spouse presentgrade byte %8.0g current grade completedunion byte %8.0g 1 if uniontenure float %9.0g job tenure, in yearshours int %8.0g usual hours workedwage float %9.0gdeath_yr float %9.0g----------------------------------------------------------------------Sorted by: idcode year Note: Dataset has changed since last saved.

我们先要考虑,对个体而言哪些变量是随时间变化而变化的,以及哪些是不变的。在这个例子中,我们的数据经过xtset并且没有字符型变量,我们可以使用xtsum指令,不随着年份变化的变量标准差为 0 。对于更一般的情况,我们可以使用distinct指令 (Cox and Longton 2008) 。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
.       distinct idcode-------------------------------        |     total   distinct--------+---------------------- idcode |     28534       4711-------------------------------
. distinct idcode grade, joint missing---------------------------------- | total distinct-----------+---------------------- (jointly) | 28534 4711----------------------------------

接下来,我们着重关注四个随时间变化的连续变量:wagetenurehoursage。我们将哪个或哪些变量画到横纵坐标轴上呢?我们需要用到变量的对数形式吗?我们对待连续型变量和字符型变量应该一样吗?顺着这样的思路,我们决定把表示年龄的数值型变量 age 作为文本写在 X 轴附近 (由于受访者并非是在不同年份的同月同日接受调查,所以年龄与年份并不是完美对应的) 。然后,对于其他三个变量,我们决定截断较大的取值,并且 wagetenure 应该在 Y 轴上相同,取值范围均为 0 ~ 20 。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
 summarize wage, detail generate wage_trunc = min(wage, 20) if !missing(wage) label variable wage_trunc "Wage ($/hour)"  summarize tenure, detail generate tenure_trunc = min(tenure, 20) if !missing(tenure) label variable tenure_trunc "Tenure (years)"  summarize hours, detail generate hours_trunc = min(hours, 60) if !missing(hours) label var hours_trunc "Usual hours worked"

下一步,我们考虑两个随时间变化的分类变量:unionmsp 。我们用"U"和"-"表示 union 的状态变化,用"M"和"-"表示 msp 的状态变化。另外,表示种族的 race 是不会随时间发生变化的变量,我们生成了一个包含 race 值标签的变量,方便我们更容易地把信息添加到时序图中。与前面的例子相类似,我们在此仅保留前六个 ID 的个体来绘图。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
 tabulate union, missing generate lab_union = "U" if union==1 replace lab_union = "-" if union==0 tabulate msp, missing generate lab_married = "M" if msp == 1 replace lab_married = "-" if msp == 0  decode race, generate(race_str) keep if idcode <= 6

下面我们来绘制六个个体的多变量时序图,与前面单变量的例子相同,我们将得到的表示这六个个体的六张图,我们把它们导出到文档中。

  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
  • ounter(line
generate y_union = 23generate y_married = 26generate y_age = 0
putdocx clearputdocx begin, landscapeputdocx paragraph
levelsof idcode, local(idcodes) cleanforeach id of local idcodes { local xline "" local xlinetext "" summarize death_yr if idcode == `id'if r(N) > 0 { local death_year = r(min) if r(min) <= 88 { local xline "xline(`death_year')" local xlinetext `"text(21 `death_year' "Died")"' }}levelsof race_str if idcode == `id', local(race_info) cleanlevelsof grade if idcode == `id', local(grade_info)
twoway (scatter wage_trunc tenure_trunc year, connect(l l) sort /// clwidth(thick) msymbol(O T)) /// (scatter y_union y_married year, msymbol(i i) /// mlabel(lab_union lab_married) mlabposition(0 0)) /// (scatter y_age year, msymbol(i) mlabel(age) mlabposition(6) /// mlabgap(*0.1) mlabcolor(gs8)) /// (scatter hours_trunc year, yaxis(2) connect(l) sort msymbol(Sh) /// clpattern(dash)) /// if idcode == `id', /// xlabel(68 "1968" 73 "1973" 78 "1978" 83 "1983" 88 "1988", notick /// labsize(small) labgap(*6)) /// xmtick(68 69 70 71 72 73 75 77 78 80 82 83 85 87 88, grid notick) /// `xline' `xlinetext' /// xscale(range(67.5 88.5)) /// plotregion(margin(zero)) /// xtitle("") /// text(-1 66 "Age", size(small) color(gs8)) /// text(-2.7 66 "Year", size(small)) /// graphregion(color(white)) /// legend(order(1 - " " 6 2) span cols(3)) /// ytitle("Wage ($/hour) " "Tenure (years) ") /// ytitle("Usual hours worked ", axis(2)) /// title("id `id'") subtitle("(`race_info', grade `grade_info')") /// ylabel(0 2 4 6 8 10 12 14 16 18 20 "≥20" 23 "Union?" 26 "Married?", /// angle(horizontal)) /// ylabel(0 6 12 18 24 30 36 42 48 54 60 "60+", axis(2) /// angle(horizontal)) /// yscale(range(0 27)) yscale(range(0 81) axis(2)) /// name(g`id', replace)
graph export "graph.png", replace putdocx image "graph.png" } putdocx save "Example 2. Individual Graphs.docx", replace erase "graph.png"

在我们得到的六张个体时序图中,以第五张为例,如下图所示: 图2. 个体多变量时序图 (idcode == 5)

通过上面单变量和多变量单个个体时序图的两个例子,你学会怎么用自己的研究数据绘制时序图了吗?快来动手试一试吧!

4. 参考文献

  • Center for Human Resource Research. 1989. National Longitudinal Survey of Labor Market Experience, Young Women 14–26 years of age in 1968. Ohio State University.
  • Cox, N. J. 2010. Speaking Stata: Graphing subsets. Stata Journal 10: 670–681. [PDF]
  • Cox, N. J., and G. M. Longton. 2008. Speaking Stata: Distinct observations. Stata Journal 8: 557–568. [PDF]

相关课程

连享会-直播课 上线了!
http://lianxh.duanshu.com

免费公开课:


课程一览

支持回看,所有课程可以随时购买观看。

专题 嘉宾 直播/回看视频
Stata暑期班 连玉君
江艇
线上直播 9 天
2020.7.28-8.7
效率分析-专题 连玉君
鲁晓东
张 宁
视频-TFP-SFA-DEA
已上线,3天
文本分析/爬虫 游万海
司继春
视频-文本分析与爬虫
已上线,4天
空间计量系列 范巧 空间全局模型, 空间权重矩阵
空间动态面板, 空间DID
研究设计 连玉君 我的特斯拉-实证研究设计-幻灯片-
面板模型 连玉君 动态面板模型-幻灯片-
直击面板数据模型 [免费公开课,2小时]

Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。


关于我们

  • Stata连享会 由中山大学连玉君老师团队创办,定期分享实证分析经验。直播间 有很多视频课程,可以随时观看。
  • 连享会-主页知乎专栏,300+ 推文,实证分析不再抓狂。
  • 公众号推文分类: 计量专题 | 分类推文 | 资源工具。推文分成 内生性 | 空间计量 | 时序面板 | 结果输出 | 交乘调节 五类,主流方法介绍一目了然:DID, RDD, IV, GMM, FE, Probit 等。
  • 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标,输入简要关键词,以便快速呈现历史推文,获取工具软件和数据下载。常见关键词:
    • 课程, 直播, 视频, 客服, 模型设定, 研究设计, 暑期班
    • stata, plus,Profile, 手册, SJ, 外部命令, profile, mata, 绘图, 编程, 数据, 可视化
    • DID,RDD, PSM,IV,DID, DDD, 合成控制法,内生性, 事件研究, 交乘, 平方项, 缺失值, 离群值, 缩尾, R2, 乱码, 结果
    • Probit, Logit, tobit, MLE, GMM, DEA, Bootstrap, bs, MC, TFP, 面板, 直击面板数据, 动态面板, VAR, 生存分析, 分位数
    • 空间, 空间计量, 连老师, 直播, 爬虫, 文本, 正则, python
    • Markdown, Markdown幻灯片, marp, 工具, 软件, Sai2, gInk, Annotator, 手写批注, 盈余管理, 特斯拉, 甲壳虫, 论文重现, 易懂教程, 码云, 教程, 知乎

连享会主页  lianxh.cn
连享会主页 lianxh.cn

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


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

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