温馨提示: 定期 清理浏览器缓存,可以获得最佳浏览体验。
徐嘉树 (中国人民大学)
jiashuxu@ruc.edu.cn
Source: Chatfield, Mark D. "Graphing each individual's data over time." The Stata Journal 18.3 (2018): 503-516. [PDF]
目录
对于纵向和面板数据,绘制单个个体随时间变化的图表是一种有效的信息探索方式,对多变量随时间变化、以及着重多个时间点的数据尤为突出。仔细研究单个个体的时序图不仅可以洞察数据的性质和质量,为进一步分析提供信息。若选择一些典型,更能够为你的研究展示提供强有力的证据。
Cox (2010) 在讨论数据图形化时,强调了个体之间或个体组之间的比较。我们在探索数据时,绘制每个个体随时间变化的数据(在单独的图表中)可能是一种容易被忽视的做法。从本质上讲,这种方法强调的是个体内部(而非个体之间)的差异。研究一些个体的时序图可以加深我们对数据的理解,并就可能对数据提出哪些研究问题、以及如何分析数据产生一些新的想法。随着时间的推移,数据中有很多关于个人的信息,绘制原始数据图可能是一项相当艰巨的挑战。各种符号和线段可以相互重叠,使我们制成的图形让人难以理解。对此,为单个个体绘制独立的时序图恰恰是一种解决办法。
接下来让我们看一看,在 Stata 中怎样绘制这些时序图。
本文将使用美国劳动力市场经验纵向调查 National Longitudinal Survey of Labor Market Experience 中 1968 年 14-26 岁年轻女性的子样本数据进行时序图的绘制。这部分数据包含在 1968 年至 1988 年的 21 年中 (除 1974 年、1976 年、1979 年、1981 年、1984 年和 1986 年外) 受访女性的工资及相关因素随时间变化的信息。我们需要在 Stata 中导入数据,并设定绘图模板。
. use http://www.stata-press.com/data/r15/nlswork.dta, clear
. xtset
. xtdescribe
. set scheme sj
在第一个简单的例子中,我们打算绘制个体工资随时间变化的时序图。首先,我们需要做一些准备工作,生成工资相关的变量。由于在我们使用的样本中有很多个体 (4711) ,在此我们只选择前六个个体做例子,来绘制六张单个个体的时序图。
. 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
绘制散点图,用ylabel
、yscale
和xlabel
、xmtick
、xscale
分别修饰 Y 轴和 X 轴的标签、刻度和范围。
putdocx clear
putdocx begin, landscape
putdocx paragraph
levelsof idcode, local(idcodes) clean
foreach 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", replace
erase "temp_graph.png"
通过以上指令,我们能够得到六张个体时序图,以第五张为例,如下图所示:
连享会计量方法专题……
接下来的第二个例子较为复杂,我们的时序图将展示这个样本中describe
指令所显示的多个变量的情况。
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 value
variable type format label variable label
----------------------------------------------------------------------
idcode int %8.0g NLS ID
year byte %8.0g interview year
age byte %8.0g age in current year
race byte %8.0g racelbl race
msp byte %8.0g 1 if married, spouse present
grade byte %8.0g current grade completed
union byte %8.0g 1 if union
tenure float %9.0g job tenure, in years
hours int %8.0g usual hours worked
wage float %9.0g
death_yr float %9.0g
----------------------------------------------------------------------
Sorted by: idcode year
Note: Dataset has changed since last saved.
我们先要考虑,对个体而言哪些变量是随时间变化而变化的,以及哪些是不变的。在这个例子中,我们的数据经过xtset
并且没有字符型变量,我们可以使用xtsum
指令,不随着年份变化的变量标准差为 0 。对于更一般的情况,我们可以使用distinct
指令 (Cox and Longton 2008) 。
. distinct idcode
-------------------------------
| total distinct
--------+----------------------
idcode | 28534 4711
-------------------------------
. distinct idcode grade, joint missing
----------------------------------
| total distinct
-----------+----------------------
(jointly) | 28534 4711
----------------------------------
接下来,我们着重关注四个随时间变化的连续变量:wage,tenure,hours 和 age。我们将哪个或哪些变量画到横纵坐标轴上呢?我们需要用到变量的对数形式吗?我们对待连续型变量和字符型变量应该一样吗?顺着这样的思路,我们决定把表示年龄的数值型变量 age 作为文本写在 X 轴附近 (由于受访者并非是在不同年份的同月同日接受调查,所以年龄与年份并不是完美对应的) 。然后,对于其他三个变量,我们决定截断较大的取值,并且 wage 和 tenure 应该在 Y 轴上相同,取值范围均为 0 ~ 20 。
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"
下一步,我们考虑两个随时间变化的分类变量:union 和 msp 。我们用"U"和"-"表示 union 的状态变化,用"M"和"-"表示 msp 的状态变化。另外,表示种族的 race 是不会随时间发生变化的变量,我们生成了一个包含 race 值标签的变量,方便我们更容易地把信息添加到时序图中。与前面的例子相类似,我们在此仅保留前六个 ID 的个体来绘图。
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
下面我们来绘制六个个体的多变量时序图,与前面单变量的例子相同,我们将得到的表示这六个个体的六张图,我们把它们导出到文档中。
generate y_union = 23
generate y_married = 26
generate y_age = 0
putdocx clear
putdocx begin, landscape
putdocx paragraph
levelsof idcode, local(idcodes) clean
foreach 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) clean
levelsof 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"
在我们得到的六张个体时序图中,以第五张为例,如下图所示:
通过上面单变量和多变量单个个体时序图的两个例子,你学会怎么用自己的研究数据绘制时序图了吗?快来动手试一试吧!
连享会-直播课 上线了!
http://lianxh.duanshu.com
免费公开课:
直击面板数据模型 - 连玉君,时长:1小时40分钟 Stata 33 讲 - 连玉君, 每讲 15 分钟. 部分直播课 课程资料下载 (PPT,dofiles等)
支持回看,所有课程可以随时购买观看。
专题 | 嘉宾 | 直播/回看视频 |
---|---|---|
⭐ 最新专题 ⭐ | DSGE, 因果推断, 空间计量等 | |
⭕ Stata数据清洗 | 游万海 | 直播, 2 小时,已上线 |
研究设计 | 连玉君 | 我的特斯拉-实证研究设计,-幻灯片- |
面板模型 | 连玉君 | 动态面板模型,-幻灯片- |
面板模型 | 连玉君 | 直击面板数据模型 [免费公开课,2小时] |
Note: 部分课程的资料,PPT 等可以前往 连享会-直播课 主页查看,下载。
关于我们
课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法
等
连享会小程序:扫一扫,看推文,看视频……
扫码加入连享会微信群,提问交流更方便
✏ 连享会学习群-常见问题解答汇总:
✨ https://gitee.com/arlionn/WD
???? 连享会学习群-常见问题解答汇总:
???? https://gitee.com/arlionn/WD