查看原文
其他

Stata绘图:复现组间均值差异图

连享会 连享会 2023-10-24

👇 连享会 · 推文导航 | www.lianxh.cn

连享会 · 因果推断实用计量方法

作者:方森辉 (南开大学)
邮箱:nkfangsenhui@163.com

温馨提示: 文中链接在微信中无法生效。请点击底部「阅读原文」。或直接长按/扫描如下二维码,直达原文:

编者按:本文参考自下文,特此致谢!
Source:Collins C, Landivar L C, Ruppanner L, et al. COVID‐19 and the gender gap in work hours[J]. Gender, Work & Organization, 2021, 28: 101-112. -PDF- -Link-


目录

  • 1. 引言

  • 2. 思路介绍

  • 3. 数据整理

  • 4. 图形复现

  • 5. 结语

  • 6. 相关推文



1. 引言

在阅读文献的过程中,我们时常会被一些精美的图表所吸引,但是这些图表背后的代码逻辑,却是作者们少有呈现的部分。Stata 作为一款统计软件,自然也拥有强大的绘图功能。在本文中,我们将结合 Collins 等 (2021) 这篇文献,使用 Stata 最基本的官方绘图命令 twoway,尝试复现文中的 Figure 1。

2. 思路介绍

原文中 Figure 1 如下:

该图形由 3 个结构一样的子图组成。因此,可以通过绘制其中一个子图 (如下图),再重复绘制多个子图实现图形复现。

通过观察该子图,初步发现其由直方图 (橙色矩形),散点图 (蓝色的圆形点和绿色的棱形点),以及虚线折线图 (灰色的虚线) 三个要素组成。根据 Stata 绘图过程,我们可以依次绘制每个要素,再结合初步绘制的图形调整相对大小。

接下来,我们将顺着这一思路复现该子图。由于文章原作者并未公布原始调查数据,我们将根据人口微观调查数据的常规数据结构和数据特征,生成与原图中统计特征相近的模拟数据,并加总得到调查年龄组-调查月度-家长类型层面数据,以符合图形绘制的要求。

3. 数据整理

一般来讲,人口调查数据是个体 ID 维度的数据,如果是多年或多个追踪调查期的数据,则为个体 ID 和调查期维度。本案例数据为同一年度内 2 月至 4 月每月连续追踪调查获得的数据,其原始数据维度为个体 ID 和月度维度。不过,我们观察 Figure 1 可以发现,原始数据并未直接提供纵轴与横轴的数据维度,需要对其进行加总。

首先,导入原始数据并观察数据维度。可以发现,原始数据为 Month-ChildID-ParentIdentity 维度。

. lxhuse data_for_survey.dta, clear
. des

Observations: 90
Variables: 6 8 Jun 2022 19:21
----------------------------------------------------------------------------------
Variable Storage Display Value
name type format label Variable label
----------------------------------------------------------------------------------
Month byte %10.0g Month 调查月份:2-4月
ChildID byte %10.0g 个体ID:1-30
Age byte %10.0g 年龄:1-17岁
AgeGroup byte %8.0g AgeGroup 年龄层分组:1=[1,5],2=[6,12],3=[13,17]
ParentIdentity byte %8.0g ParentIdentity
家长身份:1=父亲,2=母亲
ParentWorkHour double %4.1f 家长每周工作时间:小时/周
----------------------------------------------------------------------------------
Sorted by: Month ChildID

其次,加总为 Month-AgeGroup-ParentIdentity 维度的数据。

. * 生成 Month-AgeGroup-ParentIdentity 维度的数据
. net install gtools.pkg, replace // 安装命令 gcollapse
. gcollapse (mean) ParentWorkHour, by(Month AgeGroup ParentIdentity)
. des

Observations: 18
Variables: 4 8 Jun 2022 19:21
---------------------------------------------------------------------------------
Variable Storage Display Value
name type format label Variable label
----------------------------------------------------------------------------------
Month byte %10.0g Month 调查月份:2-4月
AgeGroup byte %8.0g AgeGroup 年龄层分组:1=[1,5],2=[6,12],3=[13,17]
ParentIdentity byte %8.0g ParentIdentity
家长身份:1=父亲,2=母亲
ParentWorkHour double %4.1f (mean) 家长每周工作时间:小时/周
----------------------------------------------------------------------------------
Sorted by: Month AgeGroup ParentIdentity
Note: Dataset has changed since last saved.

最后,转置为 Month-AgeGroup 维度的数据,并保存为新的数据集。

. * 转置为 Month-AgeGroup 维度的数据
. ssc install fastreshape, replace
. fastreshape wide ParentWorkHour, i(Month AgeGroup) j(ParentIdentity)
. ren (ParentWorkHour1 ParentWorkHour2) (WorkHourFather WorkHourMother)
. /*根据此前设定的标签重命名变量*/

. gen WorkHourGap=abs(WorkHourFather-WorkHourMother)
. /*计算两组均值的差异, 这里 WorkHourFather 的取值均大于 WorkHourMother,
> 但实际数据中两个组别的均值相对大小是未知的,
> 因此添加一个 abs() 运算符以取两个组别均值差异的绝对值*/

. la var WorkHourFather "Fathers' Work Hours"
. la var WorkHourMother "Mothers' Work Hours"
. la var WorkHourGap "Gender Gap in Work Hours"

. gen invWorkHourGap=51-WorkHourGap*0.85 // 60 为图像的右端点, 也参与构成 xlab 的范围区间
. la var invWorkHourGap "Gender Gap in Work Hours"
. /*对新生成的 "逆" (inv=inverse) WorkHourGap 采用相同标签命名, 以标识其含义与 WorkHourGap 一致*/

. replace Month=Month+4 if AgeGroup==2
. replace Month=Month+8 if AgeGroup==1
. la def Month 2 "February" 3 "March" 4 "April" 6 "February" 7 "March" 8 "April" ///
> 10 "February" 11 "March" 12 "April", replace
. la val Month Month
. /*由于本案例是三组数据构成三个子图纵向拼接到一起, 因此需要对调查月份变换取值并添加新的值标签*/

. des
Observations: 9
Variables: 6 25 Jul 2022 16:48
---------------------------------------------------------------------------------
Variable Storage Display Value
name type format label Variable label
----------------------------------------------------------------------------------
Month byte %10.0g Month 调查月份:2-4月
AgeGroup byte %8.0g AgeGroup 年龄层分组:1=[1,5],2=[6,12],3=[13,17]
WorkHourFather double %4.1f Fathers' Work Hours
WorkHourMother double %4.1f Mothers' Work Hours
WorkHourGap float %9.0g Gender Gap in Work Hours
invWorkHourGap float %9.0g Gender Gap in Work Hours
----------------------------------------------------------------------------------
Sorted by:
Note: Dataset has changed since last saved.

. list // 显示绘图前的最后数据, 其中 Month 和 AgeGroup 显示的是值标签
+-----------------------------------------------------------------+
| Month AgeGroup Wo~ather Wo~other WorkHo~p invWor~p |
|-----------------------------------------------------------------|
1. | February [1,5] 41.1 36.2 4.9 46.835 |
2. | February [6,12] 41.7 37.0 4.7 47.005 |
3. | February [13,17] 42.6 38.3 4.3 47.345 |
4. | March [1,5] 41.6 36.1 5.5 46.325 |
5. | March [6,12] 41.5 36.4 5.1 46.665 |
|-----------------------------------------------------------------|
6. | March [13,17] 42.6 38.4 4.2 47.43 |
7. | April [1,5] 40.6 34.4 6.2 45.73 |
8. | April [6,12] 41.5 35.2 6.3 45.645 |
9. | April [13,17] 41.4 36.8 4.6 47.09 |
+-----------------------------------------------------------------+

. list, nolabel // 显示绘图前的最后数据, 其中 Month 和 AgeGroup 显示的是数值, 绘图时选项 if 使用的是数值
+--------------------------------------------------------------+
| Month AgeGroup Wo~ather Wo~other WorkHo~p invWor~p |
|--------------------------------------------------------------|
1. | 10 1 41.1 36.2 4.9 46.835 |
2. | 6 2 41.7 37.0 4.7 47.005 |
3. | 2 3 42.6 38.3 4.3 47.345 |
4. | 11 1 41.6 36.1 5.5 46.325 |
5. | 7 2 41.5 36.4 5.1 46.665 |
|--------------------------------------------------------------|
6. | 3 3 42.6 38.4 4.2 47.43 |
7. | 12 1 40.6 34.4 6.2 45.73 |
8. | 8 2 41.5 35.2 6.3 45.645 |
9. | 4 3 41.4 36.8 4.6 47.09 |
+--------------------------------------------------------------+

. di _N
. compress
. save data_for_Figure, replace

4. 图形复现

本部分主要依托于 twoway 的子命令 droplinescatter,对某个年龄层组别 (AgeGroup) 绘制多个图层来构成一个子图,然后对其他年龄层组别重复操作实现 Figure 1 的绘制。总体来看属于使用基本官方命令绘制复杂图形的一个案例。

. use data_for_Figure, clear
. tw (dropline WorkHourFather Month if AgeGroup==1, base(30) ms(i) lc(gray*0.6%80) ///
> lp(shortdash) lw(*2.5) horizontal) ///
> /*dropline 用于绘制灰色线, 选项 lp(shortdash) 与 lw(*2.5) 搭配绘制出类似散点的效果, ///
> 可以更换为其他线型*/ ///
> (dropline WorkHourMother Month if AgeGroup==1, base(30) ms(i) lc(gray*0.6%80) ///
> lp(shortdash) lw(*2.5) horizontal) ///
> (sc Month WorkHourFather if AgeGroup==1, ms(O) msize(*1.2) mc(ebblue*2) ///
> mlabel(WorkHourFather) mlabc(black) mlabs(*1.1) mlabp(12) mlabg(*1.5)) ///
> /*sc=scatter 用于绘制蓝色的圆形点*/ ///
> (sc Month WorkHourMother if AgeGroup==1, ms(d) msize(*1.2) mc(dkgreen*0.75) ///
> mlabel(WorkHourMother) mlabc(black) mlabs(*1.1) mlabp(12) mlabg(*1.5)) ///
> /*sc=scatter 用于绘制绿色的棱形点*/ ///
> (dropline invWorkHourGap Month if AgeGroup==1, base(51) ms(i) lc(dkorange*0.8) ///
> lp(solid) lw(*12) horizontal mlabel(WorkHourGap) mlabc(black) mlabs(*1.1) mlabp(9)) ///
> /*dropline 用于绘制橙黄色的直方图, 选项 lp(solid) 与 lw(*12) 搭配, ///
> 可以实现将线变宽实现类似直方图的效果, 也可以使用 addplot 与 graph hbar 的组合命令*/ ///
> (dropline WorkHourFather Month if AgeGroup==2, base(30) ms(i) lc(gray*0.6%80) ///
> lp(shortdash) lw(*2.5) horizontal) ///
> (dropline WorkHourMother Month if AgeGroup==2, base(30) ms(i) lc(gray*0.6%80) ///
> lp(shortdash) lw(*2.5) horizontal) ///
> (sc Month WorkHourFather if AgeGroup==2, ms(O) msize(*1.2) mc(ebblue*2) ///
> mlabel(WorkHourFather) mlabc(black) mlabs(*1.1) mlabp(12) mlabg(*1.5)) ///
> (sc Month WorkHourMother if AgeGroup==2, ms(d) msize(*1.2) mc(dkgreen*0.75) ///
> mlabel(WorkHourMother) mlabc(black) mlabs(*1.1) mlabp(12) mlabg(*1.5)) ///
> (dropline invWorkHourGap Month if AgeGroup==2, base(51) ms(i) lc(dkorange*0.8) ///
> lp(solid) lw(*12) horizontal mlabel(WorkHourGap) mlabc(black) mlabs(*1.1) mlabp(9)) ///
> (dropline WorkHourFather Month if AgeGroup==3, base(30) ms(i) lc(gray*0.6%80) ///
> lp(shortdash) lw(*2.5) horizontal) ///
> (dropline WorkHourMother Month if AgeGroup==3, base(30) ms(i) lc(gray*0.6%80) ///
> lp(shortdash) lw(*2.5) horizontal) ///
> (sc Month WorkHourFather if AgeGroup==3, ms(O) msize(*1.2) mc(ebblue*2) ///
> mlabel(WorkHourFather) mlabc(black) mlabs(*1.1) mlabp(12) mlabg(*1.5)) ///
> (sc Month WorkHourMother if AgeGroup==3, ms(d) msize(*1.2) mc(dkgreen*0.75) ///
> mlabel(WorkHourMother) mlabc(black) mlabs(*1.1) mlabp(12) mlabg(*1.5)) ///
> (dropline invWorkHourGap Month if AgeGroup==3, base(51) ms(i) lc(dkorange*0.8) ///
> lp(solid) lw(*12) horizontal mlabel(WorkHourGap) mlabc(black) mlabs(*1.1) mlabp(9)) ///
> , xlab(30(25)55 30 " " 55 " " 37 "Work Hours" 47 "Gender Gap in Work Hours", nogrid ///
> noticks labsize(*0.8)) ///
> /*横轴的标签, 选项 nogrid 去除图内的网格线, 选项 noticks 去除横轴的刻度*/ ///
> ylab(1(11.5)12.5 1 " " 12.5 " " 2 "February" 3 "March" 4 "April" 6 "February" ///
> 7 "March" 8 "April" 10 "February" 11 "March" 12 "April", nogrid noticks angle(0) ///
> labsize(*0.8)) ytitle("Survey Month") yscale(reverse) ///
> /*选项 yscale(reverse) 让纵轴刻度大小反转, 从上到下的数值依次增大*/ ///
> graphregion(color(white)) title("Gender Gap in Hours Worked among Parents") ///
> legend(order(4 "Mothers' Work Hours" 3 "Fathers' Work Hours" ///
> 5 "Gender Gap in Work Hours") cols(2) rows(2) size(*0.8)) ///
> /*选项 legend(order()) 设定图例, 注意这里需要结合绘制的曲线顺序来设置需要的图例*/ ///
> text(3 54 "[13,17]") text(7 54 "[6,12]") text(11 54 "[1,5]") text(1 54 "Children") ///
> text(1.5 54 "Aged Group") ///
> /*选项 text 设定图像右侧的组别说明, 需要根据图像显示效果手动调整位置和字体大小*/ ///
> xsize(12) ysize(10) ///
> /*选项 xsize 和 ysize 设置图像的长宽比例, 建议与要输出的 png 等格式图片的长宽比例一致,
> 以保证绘制出来的图像显示效果与最终导出的图像效果一致*/

. gr save "FigureGenderGap", replace
. gr export "FigureGenderGap.png", replace as(png) height(2000) width(2400)
. /*选项 height(2000) 和 width(2400) 设置图像纵向高度和横向宽度, 默认单位为像素*/

与论文中 Figure 1 相比,本次图形复现结合 Stata 的绘图特点进行了一定修改,最终绘制的图形如下:

5. 结语

以上就是 Figure 1 图形复现的基本介绍,本案例为我们如何复现已有文献的图形提供了一些思路:不论已有图形多复杂,只要化整为零,即使采用 twoway 命令也可以复现出较为复杂的图形。当然,在论文中展示精美图形的同时,也需要对图形作出恰到好处的释义,以更好服务于论文故事的讲述,起到一种锦上添花的效果。

6. 相关推文

Note:产生如下推文列表的 Stata 命令为:
lianxh 绘图, m
安装最新版 lianxh 命令:
ssc install lianxh, replace

  • 专题:Stata教程

    • Stata绘图:环形柱状图-实时全球新冠确诊人数
    • 普林斯顿Stata教程(二) - Stata绘图
  • 专题:Stata绘图

    • Stata绘图:addplot-层层叠加轻松绘图
    • Stata 绘图:用 Stata 绘制一打精美图片-schemes
    • 常用科研统计绘图工具介绍
    • Stata空间计量:莫兰指数绘图moranplot命令介绍
    • Stata绘图-组间差异可视化:不良事件火山图、点阵图
    • Stata绘图极简新模板:plotplain和plottig-T251
    • 给你的图形化个妆:Stata绘图常用选项汇总-上篇
    • 给你的图形化个妆:Stata绘图常用选项汇总-下篇
    • Stata绘图:柱状图专题-T212
    • Stata绘图:回归系数可视化-论文更出彩
    • Stata绘图:世行可视化案例-条形图-密度函数图-地图-断点回归图-散点图
    • Stata绘图:随机推断中的系数可视化
    • Stata绘图:重新定义坐标轴刻度标签
    • Stata绘图:用-bytwoway-实现快速分组绘图
    • Stata绘图:一个干净整洁的-Stata-图形模板qlean
    • Stata绘图:怎么在Stata图形中附加水平线或竖直线?

课程推荐:因果推断实用计量方法
主讲老师:丘嘉平教授
🍓 课程主页https://gitee.com/lianxh/YGqjp

New! Stata 搜索神器:lianxhsongbl  GIF 动图介绍
搜: 推文、数据分享、期刊论文、重现代码 ……
👉 安装:
. ssc install lianxh
. ssc install songbl
👉  使用:
. lianxh DID 倍分法
. songbl all

🍏 关于我们

  • 连享会 ( www.lianxh.cn,推文列表) 由中山大学连玉君老师团队创办,定期分享实证分析经验。
  • 直通车: 👉【百度一下: 连享会】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存