G8. 27个Stata绘图范例
作者: 孙晓艺 (厦门大学)
邮箱: sunnalzu202107@163.com
本文摘译自以下文章,特此致谢! Source: Fahad Mirza, 2022. Blog. Top 25 Stata Visualizations — With Full Code, -Link-
数据可视化可以帮助我们将大量的数据以易于理解的方式呈现给读者,我们学完 stata 后,在实操时可能经常会遇到这样一个问题:我应该选取哪种可视化方式才能呈现出我想要的效果?实际上,数据可视化的目的可能有很多,但概括起来大致包括以下四种:描述关联性关系、偏差关系、排序关系或分布关系,我们需要达到的可视化效果很可能属于其中一个或多个类别。笔者在正文具体展示了四种可视化效果下共 25 种 stata 图表类型,并附有完整代码,希望可以帮助读者找到适合的可视化工具。
A. 命令安装
我们在开始介绍之前,需要先在 stata 中安装各类绘图命令:
ssc install schemepack, replace
ssc install colrspace, replace
ssc install palettes, replace
ssc install labutil, replace
ssc install violinplot, replace
ssc install dstat, replace
ssc install moremata, replace
接着,我们将对关联关系图(Correlation)、偏差关系图 (Deviation)、排序关系图(Ranking)和分布关系图(Distribution)四类分别展开介绍。
B. 关联关系图
通过以下八种可视化工具,我们可以检验两个变量之间的相关性强度。
1. 散点图 (Scatterplot)
散点图是数据可视化最常用的方法之一,它主要用于研究两个变量之间的关系和性质。
基本命令:twoway scatter
同时,twoway (scatter y x) (lowess y x)
可以绘制散点图和拟合曲线的叠加图。
范例如下:
sysuse auto, clear
twoway (scatter price mpg, mcolor(%60) mlwidth(0)) ///
lowess price mpg), ///
(title("{bf}Scatterplot", pos(11) size(2.75)) /// 标题
subtitle("Price Vs. MPG", pos(11) size(2.5)) /// 副标题
legend(off) /// 图例说明,`legend(off)` 表示无图例
scheme(white_tableau) // 绘图模板使用白色
关于各选项 (option) 的具体说明可详见推文 给你的图形化个妆:Stata绘图常用选项汇总-上篇;给你的图形化个妆:Stata绘图常用选项汇总-下篇 或在 \(Stata\) 中查看帮助文件:help twoway
、help scatter
命令运行结果见下图:
2. 分组散点图 (Scatterplot by Group)
如果我们想要分别绘制两组的散点图,并在一张图表中展示,可以使用下面的代码实现。
基本命令: twoway scatter
不同于一般散点图,分组散点图需要提前指定或创建分组变量,并在绘制前使用 foreach
命令循环生成并存储两组散点图的代码。
范例如下:
sysuse auto, clear
levelsof foreign, local(foreign)
foreach category of local foreign {
local scatter `scatter' scatter price mpg if foreign == `category', ///
mcolor(%60) mlwidth(0) ||
}
twoway `scatter' (lowess price mpg), ///
title("{bf}Scatterplot", pos(11) size(2.75)) ///
subtitle("Price Vs. MPG", pos(11) size(2.5)) ///
legend(order(1 "Domestic" 2 "Foreign") size(2)) ///
scheme(white_tableau)
命令运行结果见下图:
根据 \(foreign\) 变量分为 \(Domestic\) 和 \(Foreign\) 两组,分别绘制国产车和进口车行车里程 (mileage) 与价格 (price) 的散点图,并添加整体数据的拟合曲线。
另外,如果我们想要同时分组绘制散点图和拟合曲线,只需要在循环生成散点图代码时加上 lowess
命令行即可。
依照上例,范例代码为:
sysuse auto, clear
levelsof foreign, local(foreign)
foreach category of local foreign {
local scatter `scatter' scatter price mpg if foreign == `category', ///
mcolor(%60) mlwidth(0) ||local lowess `lowess' lowess price mpg if foreign == `category', ///
mcolor(%60) mlwidth(0) ||
}twoway `scatter' `lowess', ///
title("{bf}Scatterplot", pos(11) size(2.75)) ///
subtitle("Price Vs. MPG", pos(11) size(2.5)) ///
legend(order(1 "Domestic" 2 "Foreign") size(2)) ///
scheme(white_tableau)
命令运行结果如下图:
3. 抖动图 (Jitter Plot)
在散点图中,所有数据都用垂直线对齐,虽然看起来更加整洁,但是我们可以发现绘图区域上的点数与数据观测值的数量并不相等,主要是因为这些点相互重叠,扭曲了基础数据。为了观测完整数据,我们需要使用 jitter
命令来随机分散这些点。
基本命令:scatter y x, jitter()
抖动图命令与散点图类似,但需要在后面加上 jitter()
选项,括号内填写抖动值,抖动值越大,这些点就越分散。
范例代码如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
twoway (scatter hwy cty, jitter(5) mcolor(%60) mlwidth(0)) ///
lfit hwy cty), ///
(title("{bf}Jittered points", pos(11) size(2.75)) ///
subtitle("mpg: City vs Highway mileage", pos(11) size(2.5)) ///
legend(off) ///
scheme(white_tableau)
// `lift` 为拟合直线,上述 `lowess` 为拟合曲线
// pos(11) 表示将标题放在图形11点钟附近,即左上角
命令运行结果见下图:
4. 计数图 (Counts Chart)
对于散点图中无法展示的重叠数据,除了使用抖动图分散观测数据这个方法之外,我们也可以使用计数图展示。在计数图中,将重叠数据标记加权,随着重叠点数的增加,标记的大小也随之扩大。
基本命令:scatter y x [aw = count]
其中,[aw = count]
是一种权重选项,用于指定观测值的权重。 \(count\) 表示某数据值出现的次数,在散点图中,该权重选项将根据变量 \(count\) 的值为每个观测点分配权重。这意味着具有更高 \(count\) 值的观测点将在图形中显示为更大的点,而具有较低 \(count\) 值的观测点将显示为更小的点。
需要注意的是,在使用基本命令绘制计数图之前,我们需要通过以下两步创建权重变量 \(count\) : 第一步: 使用 group
函数,标识 y 和 x 变量中的唯一值; 第二步: 使用 count()
函数对 y 和 x 变量中的各个唯一值计数,生成权重变量 \(count\)
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
egen total = group(cty hwy)
bysort total: egen count = count(total)
twoway (scatter hwy cty [aw = count],mcolor(%60) mlwidth(0) msize(1)) ///
lfit hwy cty), ///
(title("{bf}Counts plot", pos(11) size(2.75)) ///
subtitle("mpg: City vs Highway mileage", pos(11) size(2.5)) ///
legend(off) ///
scheme(white_tableau)
命令运行结果见下图:
5. 气泡图 (Bubble Chart)
气泡图是散点图的变体,可以同时展示三个变量之间的关系,其中,x 轴和 y 轴分别代表两个变量的信息,气泡的大小反映了第三个变量的信息。
基本命令:twoway scatter y x [fw = weight]
其中,\(weight\) 为权重变量,需要指定或提前生成
为了使气泡图更好地展示变量之间的关系,我们可以另外增加以下工作: 1. 指定类别变量,分组绘制不同类别下的气泡图; 2. 添加 line
、 lifit
或 lowess
指令,绘制散点图和拟合线的叠加图; 3. 在 scatter
命令后增加 jitter()
选项,可以在散点图中添加抖动,以避免重叠,观测完整数据; 4. 在 scatter
命令后增加 mcolor()
选项,指定散点颜色,有助于区分不同类别的气泡图。
范例代码如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
** 明确绘制气泡图的分组变量 manufacturerkeep if inlist(manufacturer, "audi", "ford", "honda", "hyundai")
** 生成权重变量 `weight` recode hwy (15 16 17 18 19 = 1) (20 21 22 23 24 = 4) (25 26 27 28 29 = 8) ///
gen(weight)
(30 31 32 33 34 = 16) (35 36 = 32),
** 使用循环,分组绘制四种 manufacturer 的气泡图levelsof manufacturer, local(options)
local wordcount : word count `options'
local i = 1
foreach option of local options {
`wordcount') nograph
colorpalette tableau, n(
local scatter `scatter' scatter cty displ [fw = weight] ///
if manufacturer == "`option'", ///
"`r(p`i')'%60") mlwidth(0) jitter(10) ||
mcolor(
local line `line' lfit cty displ ///
if manufacturer == "`option'", lcolor("`r(p`i')'") ||
local ++i
}
twoway `scatter' `line', ///
title("{bf}Bubble Chart", pos(11) size(2.75)) ///
subtitle("mpg: Displacement vs City mileage", pos(11) size(2.5)) ///
ytitle("City Mileage", size(2)) ///
legend(order(3 "Honda" 4 "Hyundai" 1 "Audi" 2 "Ford" ) size(2)) ///
scheme(white_tableau)
命令运行结果见下图:
该气泡图描述了四家不同制造商(\(manufacturer\))生产的车辆,发动机排量(\(Displacement\))和城市里程(\(City Mileage\))、公路里程(\(Highway mileage\))之间的关系。x 轴和 y 轴分别为发动机排量(\(Displacement\))和城市里程(\(City Mileage\)),气泡大小代表不同等级的公路里程(\(Highway mileage\))。
6. 边缘直方图 (Marginal Histogram)
边缘直方图可以同时展示两个变量之间的关系和各自的分布情况。
绘制边缘直方图,需要分别绘制出计数图和 \(x\) 轴、 \(y\) 轴变量各自的直方图。基本步骤如下:
第一步: 绘制计数图,命名为 \(main\) ,基本命令: twoway (scatter y x [aw = count]) (lfit y x) name(main, replace)
第二步: 绘制 x 轴变量的直方图,命名为 \(xhist\),基本命令: twoway (histogram x, name(xhist, replace)
第三步: 绘制 y 轴变量的直方图,命名为 \(yhist\),基本命令同上: twoway (histogram y, horizontal, name(yhist, replace)
其中,horizontal
表示直方图是水平的,而非默认的垂直,便于后面叠加。 (在绘制直方图时需要注意的是,以上只是基本命令,由于直方图需要分别叠加在计数图的上方和右侧,在绘制时,需要添加 fysize
或 fxsize
以及 graphregion
等选项,调整直方图的高度和宽度等,具体代码见如下范例。)
第四步: 叠加计数图和两个直方图,基本命令: graph combine xhist main yhist
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
egen total = group(cty hwy)
bysort total: egen count = count(total)
** 绘制主图-计数图twoway (scatter hwy cty [aw = count], ///
legend(off)) ///
mcolor(%60) mlwidth(0) msize(1) lfit hwy cty), legend(off) name(main, replace) ///
(ytitle("Highway MPG") xtitle("City MPG") ///
margin(t=-5))
graphregion(// graphregion() 指定图形的区域参数
** 绘制 x 轴变量直方图twoway (histogram cty, yscale(off) xscale(off) ///
ylabel(, nogrid) xlabel(, nogrid) bin(30)), ///
name(cty_hist, replace) graphregion(margin(l=16)) fysize(15)
// fysize() 设置图形的高度
y 轴变量直方图
** 绘制 twoway (histogram hwy, horizontal yscale(off) xscale(off) ///
ylabel(, nogrid) xlabel(, nogrid) bin(30)), ///
name(hwy_hist, replace) graphregion(margin(b=15 t=-5)) fxsize(20)
// fxsize() 设置图形的宽度
** 三图叠加 graph combine cty_hist main hwy_hist, ///
scheme(white_tableau) ///
hole(2) commonscheme title("{bf}Marginal Histogram - Scatter Count plot", size(2.75) pos(11)) ///
subtitle("mpg: Highway vs. City Mileage", size(2.5) pos(11))
命令运行结果见下图:
7. 边缘箱图 (Marginal Boxplot)
边缘箱图也可以同时展示两个变量之间的关系和各自的分布情况,与边缘直方图的不同之处在于,边缘箱图使用箱图代替直方图,看起来更加简约。主要绘制步骤如下:
第一步: 绘制计数图,命名为 \(main\),基本命令: twoway (scatter y x [aw = count]) (lfit y x) name(main, replace)
;
第二步: 绘制 \(x\) 轴变量的箱图,命名为 \(xbox\),主要包括三部分: ① 绘制一条从上四分位数到最大异常值之间的线段,基本命令为:
`p75_`var'' 1 `max_`var'uq' 1, recast(line) scatteri
其中,scatteri
命令用于绘制散点图,但可以通过指定 recast (line)
选项用于绘制线条图。 ② 绘制一个代表变量中位数的方块,基本命令:
`med_p_`var'', ms(square) scatteri 1
③ 绘制一条从下四分位数到最小异常值之间的线段,基本命令:
`p25_`var'' 1 `min_`var'lq' 1, recast(line) scatteri
第三步: 绘制 \(y\) 轴变量的箱图,命名为 \(ybox\),基本命令同上;
第四步: 叠加计数图和两个箱图,基本命令: graph combine xbox main ybox
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited egen total = group(cty hwy)
bysort total: egen count = count(total)
** 绘制计数图 twoway (scatter hwy cty [aw = count], ///
legend(off)) ///
mcolor(%60) mlwidth(0) msize(1) lfit hwy cty), legend(off) name(main, replace) ///
(ytitle("Highway MPG") xtitle("City MPG") ///
margin(t=-5))
graphregion(
y 轴变量的箱图
** 使用循环分别绘制 x 轴和 local i = 1
local j = 10
foreach var of varlist hwy cty {
sort `var', stable
quietly summarize `var', detail
local mean_`var' = `r(mean)'
local med_p_`var' = `r(p50)'
local p75_`var' = `r(p75)'
local p25_`var' = `r(p25)'
local iqr_`var' = `p75_`var'' - `p25_`var''
generate `var'uq = `var' if `var' <= `=`p75_`var''+(1.5*`iqr_`var'')'
generate `var'lq = `var' if `var' >= `=`p25_`var''-(1.5*`iqr_`var'')'
quietly summarize `var'uq
local max_`var'uq = `r(max)'
quietly summ `var'lq
local min_`var'lq = `r(min)'
if `i' == 1 {
colorpalette tableau, nographlocal lines`i' ///
`p75_`var'' 1 `max_`var'uq' 1, recast(line) lpattern(solid) lcolor("`r(p`j')'") lwidth(1)) || ///
(scatteri `p25_`var'' 1 `min_`var'lq' 1, recast(line) lpattern(solid) lcolor("`r(p`j')'") lwidth(1)) || ///
(scatteri `med_p_`var'' 1, ms(square) mcolor(background) msize(2)) || ///
(scatteri `med_p_`var'' 1, ms(square) mcolor("`r(p`j')'")) ||
(scatteri
}
else {
colorpalette tableau, nographlocal lines`i' ///
`p75_`var'' 1 `max_`var'uq', recast(line) lpattern(solid) lcolor("`r(p`j')'") lwidth(1)) || ///
(scatteri 1 `p25_`var'' 1 `min_`var'lq', recast(line) lpattern(solid) lcolor("`r(p`j')'") lwidth(1)) || ///
(scatteri 1 `med_p_`var'', ms(square) mcolor(background) msize(2)) || ///
(scatteri 1 `med_p_`var'', ms(square) mcolor("`r(p`j')'")) ||
(scatteri 1
}
drop *lq *uq
local ++i
local j = `j' + 4
}
twoway `lines1', legend(off) xlabel(, nogrid) ///
ylabel(, nogrid) yscale(off) xscale(off) ///
name(hwy_box, replace) graphregion(margin(b=15 t=-5)) fxsize(5)
twoway `lines2', legend(off) xlabel(, nogrid) ylabel(, nogrid) ///
yscale(off) xscale(off) ///
name(cty_box, replace) graphregion(margin(l=16)) fysize(5)
** 三图叠加,绘制边缘箱图graph combine cty_box main hwy_box, ///
ycommon xcommon scheme(white_tableau) ///
hole(2) commonscheme title("{bf}Marginal Box Plot - Scatter Count plot", size(2.75) pos(11)) ///
subtitle("mpg: Highway vs. City Mileage", size(2.5) pos(11))
命令运行结果见下图:
8. 相关性热图 (Correlogram)
相关性热图用于描述多个变量之间的相关性,目前 \(Stata\) 中没有包含这一命令,因此需要手动编码,具体见范例,修改代码时只需要在 local var_corr
后面加入新的变量名,余下工作下面的代码会自动完成。
sysuse auto, clear
local var_corr price mpg trunk weight length turn foreign // 定义变量列表
local countn : word count `var_corr'
** 计算相关系数,保存在相关系数矩阵Cquietly correlate `var_corr'
matrix C = r(C)
local rnames : rownames C
** 清除当前数据集clear
** 创建并填充新数据集local tot_rows : display `countn' * `countn'
set obs `tot_rows'
generate corrname1 = ""
generate corrname2 = ""
generate y = .
generate x = .
generate corr = .
generate abs_corr = .
local row = 1
local y = 1
local rowname = 2
foreach name of local var_corr {
forvalues i = `rowname'/`countn' {
local a : word `i' of `var_corr'
replace corrname1 = "`name'" in `row'
replace corrname2 = "`a'" in `row'
replace y = `y' in `row'
replace x = `i' in `row'
replace corr = round(C[`i',`y'], .01) in `row'
replace abs_corr = abs(C[`i',`y']) in `row'
local ++row
}
local rowname = `rowname' + 1
local y = `y' + 1
}
drop if missing(corrname1)
replace abs_corr = 0.1 if abs_corr < 0.1 & abs_corr > 0.04
colorpalette HCL pinkgreen, n(10) nograph intensity(0.65)
generate colorname = ""
local col = 1
forvalues colrange = -1(0.2)0.8 {
replace colorname = "`r(p`col')'" if corr >= `colrange' & corr < `=`colrange' + 0.2'
replace colorname = "`r(p10)'" if corr == 1
local ++col
}
** 循环生成散点图代码forvalues i = 1/`=_N' {
local slist "`slist' (scatteri `=y[`i']' `=x[`i']' "`: display %3.2f corr[`i']'", mlabposition(0) msize(`=abs_corr[`i']*15') mcolor("`=colorname[`i']'"))"
}
y 轴标签
** 收集 y, val(corrname1)
labmask
labmask x, val(corrname2)
levelsof y, local(yl)
foreach l of local yl {
local ylab "`ylab' `l' `" "`:lab (y) `l''" "'"
}
** 收集 x 轴标签levelsof x, local(xl)
foreach l of local xl {
local xlab "`xlab' `l' `" "`:lab (x) `l''" "'"
}
**绘图twoway `slist', title("Correlogram of Auto Dataset Cars", size(3) pos(11)) ///
note("Dataset Used: Sysuse Auto", size(2) margin(t=5)) ///
xlabel(`xlab', labsize(2.5)) ylabel(`ylab', labsize(2.5)) ///
xscale(range(1.75 )) yscale(range(0.75 )) ///
ytitle("") xtitle("") ///
legend(off) ///
///
aspect(1) scheme(white_tableau)
命令运行结果见下图:
C. 偏差关系图(Deviation)
9. 发散条形图 (Diverging Bars)
发散条形图可以直观地显示数据集中某变量正值和负值的分布情况,通过绘制水平发散条形图,正值有序集中在条形图上半方,绿色显示,负值则排列在下半方,红色显示。
基本命令:
twoway (bar y x if D == 1, horizontal ///
barwidth(1.5) bcolor("`r(p3)'")) ///
lwidth(0) bar y x if D == 0, horizontal ///
(barwidth(1.5) bcolor("`r(p4)'")) lwidth(0)
其中,bar
命令用于绘制条形图,\(y\) 为我们想要展示的变量,\(x\) 为类别变量,\(D\) 为虚拟变量,通常,当 \(y>=0\) 时,\(D=1\),否则为 0,horizontal
表示绘制水平条形图,bcolor
选项用于调整颜色 。
范例如下:
sysuse auto, clear
** 计算变量标准差egen double mpg_z = std(mpg)
** 生成虚拟变量,分别绘制正值和负值集合generate above = (mpg_z >= 0)
** 对 mpg_z 排序并分配排名sort mpg_z, stable
generate rank_des = _n * 2
** 根据排名赋以标签value(make)
labmask rank_des,
** 绘图
colorpalette tableau, nograph intensity(0.8)twoway (bar mpg_z rank_des if above == 1, ///
barwidth(1.5) bcolor("`r(p3)'")) ///
horizontal lwidth(0) bar mpg_z rank_des if above == 0, ///
(barwidth(1.5) bcolor("`r(p4)'")), ///
horizontal lwidth(0) ytitle("") xtitle("") ///
ylabel(2(2)148, valuelabel labsize(1.25) nogrid) ///
xlabel(-4(1)4, nogrid) ///
xscale(range(-4 4)) ///
legend(off) ///
title("{bf}Diverging Bars (Normalized MPG)", ///
size(2.75) pos(11)) ///
scheme(white_tableau)
命令运行结果见下图:
10. 发散型棒棒糖图 (Diverging Lollipop Graph)
发散型棒棒糖图与发散条形图整体类似,不同之处在于,发散型棒棒糖图更为精简,并标出每一类别的变量值。
基本命令为:
twoway rspike y1 y2 x
其中,\(y_1\) 为参考变量,\(y_2\) 为想要描述或展示的变量,\(x\) 为类别变量。
范例如下:
sysuse auto, clear
keep in 1/20
** 计算变量标准差egen double mpg_z = std(mpg)
** 对 mpg_z 排序并分配排名sort mpg_z, stable
generate rank_des = _n
** 根据排名赋以标签value(make)
labmask rank_des,
** 生成零点——参考点generate zero = 0
** 数据格式化并压缩tostring mpg_z, gen(mpg_z_lab) force format(%3.2f)
compress
** 绘图 twoway (rspike zero mpg_z rank_des, horizontal) ///
scatter rank_des mpg_z, ///
(mlabel(mpg_z_lab) mlabsize(1.5) mlabposition(0)), ///
msize(5.3) xlabel(-2.5(1)-0.5 0 0.5(1)2.5, labsize(2)) ///
ylabel(1(1)20, valuelabel labsize(2)) ///
legend(off) ///
ytitle("Car Name") ///
title("{bf}Diverging Lollipop Chart (Normalized MPG)", size(2.75) pos(11)) ///
scheme(white_tableau)
命令运行结果见下图:
11. 发散点图 (Diverging Dot Plot)
相比与前面两张图,发散点图也可以描述相似的信息,但是相对更加精简。
它的基本命令为:
twoway (scatter x y if D == 1, ///
"`r(p4)'") msize(5) ///
mcolor(mlabel() mlabsize(1.3) mlabposition(0)) ///
scatter x y if D == 0, ///
("`r(p3)'") msize(5) ///
mcolor(mlabel() mlabsize(1.3) mlabposition(0))
其中,bar
命令用于绘制条形图,\(y\) 为我们想要展示的变量,\(x\) 为类别变量,\(D\) 为虚拟变量,通常,当 \(y>=0\) 时,\(D=1\),否则为 0。
范例如下:
sysuse auto, clear
keep in 1/20
** 计算变量标准差egen double mpg_z = std(mpg)
** 对 mpg_z 排序并分配排名sort mpg_z, stable
generate rank_des = _n
** 根据排名赋以标签value(make)
labmask rank_des,
** 生成虚拟变量,分别绘制正值和负值集合 generate above = (mpg_z >= 0)
** 数据格式化并压缩tostring mpg_z, gen(mpg_z_lab) force format(%3.2f)
compress
** 绘图
colorpalette tableau, nograph intensity(0.8)twoway (scatter rank_des mpg_z if above == 0, ///
"`r(p4)'") msize(5) mlabel(mpg_z_lab) mlabsize(1.3) mlabposition(0)) ///
mcolor(scatter rank_des mpg_z if above == 1, ///
("`r(p3)'") msize(5) mlabel(mpg_z_lab) mlabsize(1.3) mlabposition(0)) ///
mcolor(///
, xlabel(-2.5(1)-0.5 0 0.5(1)2.5, labsize(2)) ///
ylabel(1(1)20, valuelabel labsize(2)) ///
legend(off) ///
ytitle("Car Name") ///
title("{bf}Diverging Dot Plot (Normalized MPG)", ///
size(2.75) pos(11)) ///
scheme(white_tableau)
命令运行结果见下图:
12. 发散条形图 - 相关图 (Diverging Bars — Correlation Plot)
与相关性热图相比,发散条形图也可以用来描述各变量之间的相关程度,只是将表现形式由矩阵换为了条形图。目前 \(stata\) 中还没有相关命令的安装包,因此代码较为冗杂,我们绘制发散条形图时,只需要修改 local var_corr
后面的变量名即可,余下代码会帮助完成其他的工作。
范例代码如下:
sysuse auto, clear
local var_corr price mpg trunk weight length turn foreign // 定义变量列表
local countn : word count `var_corr'
** 计算相关系数,保存在相关系数矩阵Cquietly corrci `var_corr'
matrix C = r(corr)
local rnames : rownames C
** 清除当前数据集clear
** 创建并填充新数据集local tot_rows : display `countn' * `countn'
set obs `tot_rows'
generate corrname1 = ""
generate corrname2 = ""
generate byte y = .
generate byte x = .
generate double corr = .
generate double abs_corr = .
local row = 1
local y = 1
local rowname = 2
foreach name of local var_corr {
forvalues i = `rowname'/`countn' {
local a : word `i' of `var_corr'
replace corrname1 = "`name'" in `row'
replace corrname2 = "`a'" in `row'
replace y = `y' in `row'
replace x = `i' in `row'
replace corr = C[`i',`y'] in `row'
replace abs_corr = abs(C[`i',`y']) in `row'
local ++row
}
local rowname = `rowname' + 1
local y = `y' + 1
}
drop if missing(corrname1)
//Color Blind Friendly option
colorpalette CET CBD1, n(20) nograph generate colorname = ""
local col = 1
forvalues colrange = -1(0.1)0.9 {
replace colorname = "`r(p`col')'" if corr >= `colrange' & corr < `=`colrange' + 0.1'
replace colorname = "`r(p20)'" if corr == 1
local ++col
}
generate group_corr = corrname1 + " - " + corrname2
compress
sort corr, stable
generate rank_corr = _n
values(group_corr)
labmask rank_corr,
* 绘图
** 在本地宏保存绘图代码forvalues i = 1/`=_N' {
local barlist "`barlist' (scatteri `=rank_corr[`i']' 0 `=rank_corr[`i']' `=corr[`i']' , recast(line) lcolor("`=colorname[`i']'") lwidth(*6))"
}
y 轴标签
** 在本地宏保存 levelsof rank_corr, local(yl)
foreach l of local yl {
local ylab "`ylab' `l' `" "`:lab (rank_corr) `l''" "'"
}
twoway `barlist', ///
legend(off) scheme(white_tableau) ylabel(`ylab', labsize(2.5)) ///
labsize(2.5)) ///
xlab(, ytitle("Pairs") xtitle("Correlation Coeff.") ///
title("{bf}Correlation Coefficient (Diverging Bar Plot)", size(2.75) pos(11))
命令运行结果见下图:
条形图分为两个部分,上方黄色部分表示变量之间为正相关关系,下方蓝色部分表示变量之间为负相关关系,且颜色是渐进的,相关性越强,颜色越深。
13. 发散条形图 - 带有置信区间的相关图 (Diverging Bars — Correlation Plot with Confidence Intervals)
该图和上图都属于发散条形图,但该图在展示相关系数之外,增加了置信区间的显示。基本命令见范例,同上述发散条形图,目前 \(stata\) 中还没有相关命令的安装包,我们绘制发散条形图时,只需要修改 local var_corr
后面的变量名即可,余下代码会帮助完成其他的工作。
范例如下:
sysuse auto, clear
local var_corr price mpg trunk weight length turn foreign // 定义变量列表
local countn : word count `var_corr'
** 计算相关系数,保存在相关系数矩阵C quietly corrci `var_corr'
matrix C = r(corr)
local rnames : rownames C
matrix LB = r(lb)
matrix UB = r(ub)
matrix Z = r(z)
egen miss = rowmiss(`var_corr')
count if miss == 0
local N = r(N)
** 清除当前数据集clear
** 创建并填充新数据集 local tot_rows : display `countn' * `countn'
set obs `tot_rows'
generate corrname1 = ""
generate corrname2 = ""
generate byte y = .
generate byte x = .
generate double corr = .
generate double lb = .
generate double ub = .
generate double z = .
generate double abs_corr = .
local row = 1
local y = 1
local rowname = 2
foreach name of local var_corr {
forvalues i = `rowname'/`countn' {
local a : word `i' of `var_corr'
replace corrname1 = "`name'" in `row'
replace corrname2 = "`a'" in `row'
replace y = `y' in `row'
replace x = `i' in `row'
replace corr = C[`i',`y'] in `row'
replace lb = LB[`i',`y'] in `row'
replace ub = UB[`i',`y'] in `row'
replace z = Z[`i',`y'] in `row'
replace abs_corr = abs(C[`i',`y']) in `row'
local ++row
}
local rowname = `rowname' + 1
local y = `y' + 1
}
drop if missing(corrname1)
p 值及显著性符号
** 生成 generate N = `N'
generate double p = min(2 * ttail(N - 2, abs_corr * sqrt(N - 2) / sqrt(1 - abs_corr^2)), 1)
generate stars = "*" if p <= 0.1 & p > 0.05
replace stars = "**" if p <= 0.05 & p > 0.01
replace stars = "***" if p <= 0.01
** 生成颜色代码 //Color Blind Friendly option
colorpalette CET CBD1, n(20) nograph generate colorname = ""
local col = 1
forvalues colrange = -1(0.1)0.9 {
replace colorname = "`r(p`col')'" if corr >= `colrange' & corr < `=`colrange' + 0.1'
replace colorname = "`r(p20)'" if corr == 1
local ++col
}
** 生成新变量,组合描述变量相关系数generate group_corr = corrname1 + " - " + corrname2
compress
** 对相关系数进行排序并分配排名sort corr, stable
generate rank_corr = _n
values(group_corr)
labmask rank_corr,
** 在本地宏保存绘图代码forvalues i = 1/`=_N' {
local barlist "`barlist' (scatteri `=rank_corr[`i']' 0 `=rank_corr[`i']' `=corr[`i']' , recast(line) lcolor("`=colorname[`i']'") lwidth(*6))"
}
y 轴标签
** 在本地宏保存 levelsof rank_corr, local(yl)
foreach l of local yl {
local ylab "`ylab' `l' `" "`:lab (rank_corr) `l''" "'"
}
** 绘制图表twoway `barlist' ///
white) lwidth(*2)) ///
(rspike lb ub rank_corr, horizontal lcolor(black*.5)), ///
(rspike lb ub rank_corr, horizontal lcolor(legend(off) scheme(white_tableau) ylabel(`ylab', labsize(2.5)) ///
labsize(2.5)) ///
xlab(, ytitle("Pairs") xtitle("Correlation Coeff.") ///
title("{bf}Correlation Coefficient with Confidence Interval (Diverging Bar Plot)", size(2.75) pos(11))
命令运行结果见下图:
14. 面积图 (Area Chart)
面积图适用于描述某指标与特定基线比较的百分比变化情况。
基本命令为:twoway area
范例如下:
"https://github.com/tidyverse/ggplot2/raw/main/data-raw/economics.csv", clear
import delimited
** 计算年度同比增长率generate yoy = (psavert[_n] - psavert[_n-1]) / psavert[_n-1]
** 生成新日期变量 - 年月generate monthyear = ym(year(date(date, "YMD")), month(date(date, "YMD")))
format monthyear %tm
** 绘制面积图twoway (area yoy monthyear if monthyear <= tm(1975m12), lwidth(0)), ///
format(%tmCY)) ///
xla(84(12)185, plotregion(lstyle(solid) lwidth(.1)) ///
xtitle("") ///
ytitle("% Returns for Personal savings", size(2.75)) ///
xscale(noline) yscale(noline) ///
title("{bf}Area Chart", pos(11) size(3)) ///
subtitle("% Returns for Personal Savings", pos(11) size(2.5)) ///
scheme(white_tableau)
命令运行结果见下图:
D. 排序关系图(Ranking)
15. 排序柱状图 (Ordered Bar Charts)
排序柱状图和一般柱状图基本相同,只是根据 \(y\) 轴变量值进行了排序。
基本代码为:
graph bar (asis) y, over(x, sort(1))
其中,graph bar
命令用于绘制条形图,sort(1)
代表根据graph bar
命令后的第一个变量排序,\(y\) 为条形图中展示的变量, \(x\) 为 \(x\) 轴表示的分类变量。
范例代码如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
collapse (mean) cty, by(manufacturer)
// 根据 manufacturer 分别计算 cty 平均值
** 绘图graph bar (asis) cty, over(manufacturer, sort(1) label(labsize(1.75))) ///
scheme(white_w3d) ///
title("{bf}Ordered Bar Chart", pos(11) size(2.75)) ///
ytitle("City" "Mileage", orient(horizontal) size(2)) ///
ylabel(, labsize(2)) ///
subtitle("Make Vs. Avg. Mileage", pos(11) size(2.5))
命令运行结果见下图:
16. 棒棒糖图 (垂直)(Lollipop Charts - Vertical)
棒棒糖图的表达效果与排序条形图相似,但使用了“棒棒糖 (Lollipop) ”的表现形式,看起来更加简洁。
基本命令为:twoway dropline y x
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
** 为不同制造商 (manufacturer) 排序,并分配排名collapse (mean) cty, by(manufacturer)
sort cty, stable
generate order = _n
order, values(manufacturer)
labmask
** 绘图 quietly summarize order
twoway dropline cty order, ///
/// 设置点的大小为2
msize(2) yscale(range(0 25)) ///
ylabel(0(5)25) ///
ytitle("City" "Mileage", orient(horizontal)) ///
xscale(range(0.25)) ///
xlabel(`r(min)'(1)`r(max)', valuelabel labsize(1.75)) ///
xtitle("") ///
title("{bf}Lollipop Chart", pos(11) size(2.75)) ///
subtitle("Make Vs. Avg. Mileage", pos(11) size(2.5)) ///
scheme(white_w3d)
命令运行结果见下图:
17. 点阵图 (水平) (Dot Plot - Horizontal)
点阵图与棒棒糖图相似,只是减去了线段,并将图转为水平方向,它可以更加直观地显示某变量的排序情况。
基本代码: twoway dot y x, horizontal
其中,twoway dot
命令后面需要加 horizontal
选项,目的是将图形转为水平显示。
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
collapse (mean) cty, by(manufacturer)
sort cty, stable
generate order = _n
order, values(manufacturer)
labmask
quietly summarize cty
local xmin = `r(min)'
// 将 summarize 的最小值存储到本地宏 xmin 中
** 绘图 quietly summarize order
twoway dot cty order, horizontal ///
///
msize(2) yscale(range(`r(min)' `r(max)')) ///
ylabel(`r(min)'(1)`r(max)', valuelabel labsize(1.75)) ///
ytitle("Make", orient(horizontal) size(2)) ///
xscale(range(`xmin')) ///
xlabel(10(5)25, nogrid) ///
xtitle("Mileage", size(2)) ///
title("{bf}Dot Plot", pos(11) size(2.75)) ///
subtitle("Make Vs. Avg. Mileage", pos(11) size(2.5)) ///
scheme(white_w3d)
命令运行结果见下图:
18. 斜率图 (Slope Chart)
斜率图经常用来比较某指标两个时间点之间的变化情况。
基本命令为:
twoway pcspike y1 x1 y2 x2
其中, pcspike
命令用于绘制斜率图的线条,起点是 (\(x_1, y_1\)),终点是 (\(x_2, y_2\)),不同于上文边缘箱图用到的 rspike
命令,rspike
要求所有对象的连线需要两端对齐,即绘制水平或垂直线段,pcspike
可以绘制斜线。
同时,在绘制斜率图时,通常需要在斜线两端起点和终点处标记标签,此时使用 scatter
命令即可:
scatter y1 x1, ms(i) mlabposition(9) mlabel(lab1952)
scatter y2 x2, ms(i) mlabposition(9) mlabel(lab1952)
其中,ms(i)
表示不使用标记符号;mlabposition(9)
代表数据点对应的标签分别位于九点钟方向,即图表左侧;mlabel(lab1952)
表示标签的文本内容由变量 \(lab1952\) 提供。
范例如下:
"https://raw.githubusercontent.com/selva86/datasets/master/gdppercap.csv", varnames(1) clear
import delimited
rename (v2 v3) (y1952 y1957) //变量重新命名
generate negative = (y1957 < y1952)
// 创建新变量 negative ,negative=1 if y1957 < y1952
generate lab1952 = continent + ", " + string(round(y1952))
generate lab1957 = continent + ", " + string(round(y1957))
generate continent1 = 1
generate continent2 = 2
// 用来标识时间点的变量,以便在斜率图中标识出两个不同时间点的数据
colorpalette w3, nograph// 设置颜色方案为 w3,此处 nograph 表示不生成图形
** 绘图twoway (pcspike y1952 continent1 y1957 continent2 if negative == 0, ///
legend(off) lcolor("`r(p11)'")) ///
if negative == 1, ///
(pcspike y1952 continent1 y1957 continent2 legend(off) lcolor("`r(p1)'")) ///
scatter y1952 continent1, ms(i) mlabposition(9) mlabel(lab1952)) ///
(scatter y1957 continent2, ms(i) mlabposition(3) mlabel(lab1957)) ///
("{bf}Year 1952", ms(i) mlabpos(9)) ///
(scatteri 12700 1 "{bf}Year 1957", ms(i) mlabpos(3)) ///
(scatteri 12700 2 ///
, ylabel(0(4000)12000, labsize(2) nogrid) ///
ytitle("Avg." "GDP/Capita", size(2) orient(horizontal)) ///
yscale(range(0 13000)) ///
xlabel(1(1)2) ///
xscale(off) ///
xtitle("") ///
xscale(range(0.2 2.8)) ///
///
aspect(1.3) title("{bf}Slope Chart", pos(11) size(2.75)) ///
subtitle("Mean GDP per capita: 1952 Vs. 1957" " ", pos(11) size(2)) ///
margin(r=25)) ///
graphregion(scheme(white_w3d)
命令运行结果见下图:
19. 哑铃图 (Dumbbell Plot)
哑铃图可以帮助我们在同一行直观地展示某变量两个时间点的变化情况。
它的基本绘图代码为:
twoway (rspike x1 x2 y, horizontal lcolor("`r(p6)'*0.4")) ///
scatter y x1, mcolor("`r(p6)'*0.4")) ///
(scatter y x2, mcolor("`r(p6)'*0.4")) (
respike
为绘制水平或垂直线条的基本命令,通常默认绘制垂直线条,但由于哑铃图是水平线条,因而需要在命令后面添加 horizontal
选项,\(x_1\) 和 \(x_2\) 分别为 \(x\) 轴表示的两个时间点的连续变量,\(y\) 为 \(y\) 轴表示的类别变量; sactter
命令则用于绘制线条两端的端点 \((x_1, y) 、 (x_2, y)\) 。
范例代码如下:
"https://raw.githubusercontent.com/selva86/datasets/master/health.csv", varnames(1) clear
import delimited
y 轴标签
** 创建类别变量 - generate srno = _n * 3
values(area)
labmask srno,
foreach var of varlist pct* {
replace `var' = `var' * 100
}
** 绘图
colorpalette w3, nographtwoway (rspike pct_2013 pct_2014 srno, horizontal lcolor("`r(p6)'*0.4")) ///
scatter srno pct_2013, mcolor("`r(p6)'*0.4")) ///
(scatter srno pct_2014, mcolor("`r(p6)'")) ///
(///
, ylabel(3(3)78, valuelabel angle(horizontal) labsize(2)) ///
legend(order(3 "2014" 2 "2013") pos(11) row(1) size(2)) ///
ytitle("") ///
title("{bf}Dumbbell Plot", pos(11) size(2.75)) ///
subtitle("% Change in Health Indicators by Area: 2014 vs. 2013", pos(11) size(2)) ///
scheme(white_tableau)
命令运行结果见下图:
E. 分布关系图(Distribution)
20. 连续变量堆积直方图 (Histogram on Continuous Variable)
\(Stata\) 用于绘制直方图的原始命令只能做到为一个变量生成直方图,连续变量堆积直方图可以同时描述连续变量和类别变量的分布关系,展示连续变量特定水平下不同类别的分布情况。
关于连续变量堆积直方图的代码,原作者运用 \(stata\) 的 undocumented
命令运行,因而,使用时可能不够稳定,也不一定适用所有情况,如果命令有问题或者需要更新,可以给原文章的作者留言解决(Data Envelopment Analysis (DEA)Visualization using Stata, -Link-)。
范例代码如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
replace class = subinstr(class, "2", "two", .)
** 创建一个默认框架的副本 original ,用于备份数据default original, replace
frame copy
class 变量的唯一值,并存储在本地宏 cls 中
** 获取 levelsof class, local(cls)
** 遍历 cls 中的每个类别,绘制 displ 的直方图并存储foreach l of local cls {
class, into(`l')
frame put displ `l'
frame change
twoway__histogram_gen displ if class == "`l'", start(1) width(0.1) frequency generate(h x, replace)
rename (h) (h_`l')
keep x h_`l'
drop if missing(x)
save `l', replace
frame change original
}
** 将当前框架设置回 original,生成不分组的直方图并存储
frame change originaltwoway__histogram_gen displ, start(1) width(0.1) frequency generate(h x, replace)
drop h
generate tag = 1 if missing(x) // 创建一个标签变量,标识缺失值
replace x = _n if missing(x) // 将缺失值用观测编号 _n 替换
foreach l of local cls {
merge 1:1 x using `l', nogen
}
replace x = . if tag == 1
drop tag
type 新变量
** 重新组织数据集,宽变长,生成 keep x h_*
drop if missing(x)
reshape long h_, i(x) j(type) string
bysort x (type) : gen cumul_sum_ = sum(h_) if !missing(h_)
** 长变宽,将累积和变量 cumul_sum_ 转为多个变量drop h_*
reshape wide cumul_sum_, i(x) j(type) string
"cumul" 开头的所有变量
** 计数以 ds cumul*
local wcount: word count `r(varlist)'
"cumul" 变量生成条形图命令,存储在本地宏 `bar`
** 根据不同的 forvalues i = `wcount'(-1)1 {
ds cumul*
local a : word `i' of `r(varlist)'
display "`a'"
`i')
colorpalette tableau, nograph n(local bar "`bar' (bar `a' x, fcolor("`r(p`i')'") barwidth(0.1) lwidth(0.1) lcolor(gs4))"
}
// 绘制直方图
twoway `bar', xlabel(1(1)7) scheme(white_tableau) ///
legend(order(1 "2 Seater" 2 "SUV" 3 "Subcompact" 4 "Pickup" 5 "Minivan" 6 "Midsize" 7 "Compact") ///
size(2)) ///
rowgap(0) xlabel(, labsize(2)) ylabel(, labsize(2)) ///
ytitle("Count", size(2)) xtitle("Displacement", size(2)) ///
title("{bf}Histogram with Auto Binning", pos(11) size(2.75)) ///
subtitle("Engine Displacement across Vehicle Classes", pos(11) size(2))
命令运行结果见下图:
\(x\) 轴代表发动机排量(\(displacement\)),\(y\) 轴代表不同类型车辆的总数量(\(count\)),同时按照不同型号(\(class\))分类展示,该图表描述了特定发动机排量水平的车辆型号组成情况。
21. 类别变量堆积直方图 (Histogram on Categorical Variable)
不同于连续变量堆积直方图,类别变量堆积直方图 \(x\) 轴展示的是类别变量,描述给定类别变量的频率分布。
基本代码:
graph bar (count), over(y1) ///
over(y2, label(alternate labsize(2))) asyvars stack
其中, graph bar (count)
为基本命令,当基于两个分组变量 \(y_1、y_2\)时,要用两个 over()
选项,stack
选项用于将变量 \(y_1\) 堆叠为一个条形图,使图表更为精简易读。
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
** 构建本地宏 barlwidth,存储不同类别下条形图的线宽度设置 forvalues i = 1/7 {
local barlwidth "`barlwidth' bar(`i', lwidth(0)) "
}
** 绘图graph bar (count), over(class) ///
over(manufacturer, label(alternate labsize(2))) asyvars stack ///
scheme(white_w3d) ///
ylabel(, nogrid) ///
legend(order(7 "SUV" 6 "Subcompact" 5 "Pickup" 4 "Minivan" 3 "Midsize" 2 "Compact" 1 "2 Seater") ///
size(2)) ///
rowgap(0.25) ///
lintensity(*0) `barlwidth' ///
title("{bf}Histogram on Categorical Variable", pos(11) size(2.75)) ///
subtitle("Manufacturer across Vehicle Classes", pos(11) size(2))
命令运行结果见下图:
22. 密度图 (按类别划分) Density Plot (By Category)
绘制步骤主要包括两步: 第一步: 使用 foreach
命令,循环指定不同类别的密度图代码并存储在本地宏 kden
中。密度图绘制代码为 :kdensity y
,其中, kdensity
为密度图基本命令, \(y\) 为描述的连续变量; 第二步: 调用存储在本地宏 kden
的绘制代码,使用 twoway
命令绘制密度图。
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
levelsof cyl, local(cylinders)
foreach cylinder of local cylinders {
quietly summarize cty
local kden "`kden' (kdensity cty if cyl == `cylinder', range(`r(min)' `r(max)') recast(area) fcolor(%70) lwidth(*0.25))"
}
twoway `kden', scheme(white_w3d) ///
legend(subtitle("Cylinders", size(2)) label(1 "4") label(2 "5") label(3 "6") label(4 "8") rowgap(0.25) size(2)) ///
title("{bf}Density Plot", pos(11) size(2.75)) ///
ytitle("Density", size(2) orient(horizontal)) ///
ylabel(, nogrid labsize(2)) ///
xtitle("City Mileage", size(2)) ///
xlabel(, nogrid labsize(2)) ///
subtitle("City Mileage over number of cylinders", pos(11) size(2))
命令运行结果见下图:
该图绘制了不同气缸类别 \((cylinder)\) 的城市里程 \((City Mileage)\) 密度图。
23. 箱形图 (The Box Plot)
箱形图,也称盒图,箱线图,常用于反映数据的分布特征,该图是常规箱形图,使用 \(Stata\) 内置命令可以轻松绘制。
基本代码为:
graph box y, over()
其中,graph box
为基本命令,\(y\) 为想要描述的变量,over()
选项中为分组的类别变量。
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
graph box cty, over(class) ///
ytitle("City Mileage", size(2.25)) ///
ylabel(, nogrid) ///
title("{bf}Box Plot", pos(11) size(2.75)) ///
" " "Class of vehicle", size(2.5)) ///
b1title(subtitle("City Mileage grouped by class of vehicle", ///
size(2)) ///
pos(11) scheme(white_w3d)
命令运行结果见下图:
该图描述了不同汽车型号 (class) 的城市行车里程 (City Mileage) 情况。
下图红框中的横线代表中位数,红框顶部为第 75 百分位数,红框底部为第 25 百分位数,箱框上下的垂直线为“晶须”,为四分位数间距(1.5*IQR),晶须上端的水平线代表上边缘,下端的水平线代表下边缘,上下边缘以外的红点为异常值。
24. Tufte箱形图 (Tufte Style Box Plot)
Tufte箱形图与上个展示的常规箱形图都可以用来反映数据的分布情况,但Tufte箱形图相对更为简约。
基本命令: graph box
同时,需要添加以下选项: - medtype(marker)
指定中位数的显示方式为标记; - medmarker(mcolor(black) mlwidth(0))
指定中位数标记的属性,颜色为黑色,线宽度为 0,即不显示中位数标记的边框; - cwhiskers
表示使用自定义晶须; - alsize()
指定相邻线宽,alsize(0)
表示相邻线宽为0; - intensity()
指定填充箱框的颜色强度,intensity(0)
表示不填充箱框; - lines(lpattern(solid) lwidth(medium))
指定箱图的线条样式为实线,线宽为中等。 (具体可查看 \(Stata\) 帮助文件 help graph box
)
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
graph box cty, over(class) ///
color(white%0)) ///
box(1, ///
medtype(marker) black) mlwidth(0)) ///
medmarker(mcolor(///
cwhiskers ///
alsize(0) ///
intensity(0) ///
lintensity(1) ///
lines(lpattern(solid) lwidth(medium)) ylabel(, nogrid) ///
yscale(noline) ///
title("{bf}Box Plot", pos(11) size(2.75)) ///
subtitle("City Mileage over number of cylinders", ///
size(2)) ///
pos(11) scheme(white_w3d)
命令运行结果见下图:
25. 简约箱形图 (Minimalistic Box Plot)
简约箱形图也属于常规箱形图的一种简单表现形式,但是,相对于 Tufte箱形图,简约箱形图可以同时根据多个分组变量绘制不同类别的箱形图。
基本命令: graph box
同时,需要在后面添加指定的分组变量,over()
选项指定 \(x\) 轴代表的类别变量,by()
选项指定每一个方框内的不同类别。
graph box cty,
over(cyl)
by(class, row(1))
// row(1) 代表以一行的形式排列不同类别的箱图
范例如下:
"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
levelsof cyl, local(cylinders)
local catcount: word count `cylinders'
forvalues i = 1/`catcount' {
`catcount')
colorpalette tableau, nograph n(local boxopt "`boxopt' box(`i', color("`r(p`i')'")) "
}
display `"`boxopt'"'
graph box cty, over(cyl) ///
by(class, ///
row(1) legend(pos(3)) imargin(l=1.5 r=1.5) style(compact) ///
title("{bf}Box Plot", pos(11) size(2.75)) ///
subtitle("City Mileage over number of cylinders" " ", pos(11) size(2)) ///
note(, size(2)) ///
) ///
asyvars ///
`boxopt' ///
boxgap(50) ///
medtype(marker) ///
medmarker(mcolor() mlwidth(0) msize(1)) ///
cwhiskers ///
alsize(0) ///
intensity(0) ///
lintensity(1) ///
lines(lpattern(solid) lwidth(medium)) ///
ylabel(, nogrid) ///
yscale(noline) ///
ytitle("City Mileage", size(2.25)) ///
subtitle(, size(2.5)) /// //size of group headers
legend(size(2.25) rowgap(0.25) subtitle("Cylinders", size(2.25))) ///
scheme(white_tableau)
命令运行结果见下图:
26. 小提琴图 (Violin Plot)
与箱形图的不同之处在于,小提琴图可以同时看到数据的分布密度,小提琴图可以分为两种:带箱框型和不带箱框型。
带箱框的小提琴图:
基本命令:violinplot
,需要添加 over()
选项指定分组变量,添加 vertical
表示绘制垂直方向上的小提琴图。
不带箱框的小提琴图:
基本命令同上 violinplot
,但是,除 over()
和 vertical
之外,需要在后面添加选项 nobox
nomedian
noline
nowhiskers
,分别表示不绘制箱体、不展示中位数、不绘制箱线图的线条、不绘制晶须。
范例如下:
** 带箱框的小提琴图"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
over(class) vertical scheme(white_w3d) ///
violinplot cty, ytitle("City Mileage", size(2.25)) ///
ylabel(, nogrid) ///
title("{bf}Box Plot", pos(11) size(2.75)) ///
" " "Class of vehicle", size(2.5)) ///
b1title(subtitle("City Mileage grouped by class of vehicle", pos(11) size(2))
** 不带箱框的小提琴图"https://raw.githubusercontent.com/tidyverse/ggplot2/master/data-raw/mpg.csv", clear
import delimited
over(class) vertical scheme(white_w3d) nobox nomedian noline nowhiskers ///
violinplot cty, ytitle("City Mileage", size(2.25)) ///
ylabel(, nogrid) ///
title("{bf}Box Plot (Density Only)", pos(11) size(2.75)) ///
" " "Class of vehicle", size(2.5)) ///
b1title(subtitle("City Mileage grouped by class of vehicle", pos(11) size(2))
命令运行结果见下图:
带箱框的小提琴图:
不带箱框的小提琴图:
27. 人口金字塔图 (Population Pyramid Plot)
金字塔图可以用来反映某变量在不同时间或阶段的特征,常用于表示人口的婚姻状况、受教育程度、不同产业部门的产值、不同部门的职工人数、收入和消费水平等。
基本命令:
twoway (bar x y if D == 1, horizontal lwidth(0) barwidth(0.8)) ///
bar x y if D == 0, horizontal lwidth(0) barwidth(0.8)) (
金字塔图的基本绘制命令同条形图 twoway bar
,不同之处在于,金字塔图需要添加 horizontal
选项,指定水平绘制,同时设置分类变量 \(D\) ,分组绘制水平条形图。金字塔图的水平柱表示 \(x\) 变量的数量特征,垂直柱表示类别变量 \(y\) 。
范例如下:
"https://raw.githubusercontent.com/selva86/datasets/master/email_campaign_funnel.csv", clear
import delimited
format users %20.0g
replace users = round(users)
replace users = -(users) if users < 0 & gender == "Female"
replace users = -(users) if users > 0 & gender == "Male"
encode stage, gen(stage_n)
** 循环生成 xlab 变量,用于设置x轴的刻度标签forvalues i = -15000000(5000000)15000000 {
if `i' != 0 {
local xlab "`xlab' `i' `"`=abs(`i')/1000000'm"'" //Use of compound quotes to work with labels with absolute (abs) values
}
else {
local xlab "`xlab' 0 `"0"'"
}
}
** 绘图twoway (bar users stage_n if gender == "Female", horizontal lwidth(0) barwidth(0.8)) ///
bar users stage_n if gender == "Male", horizontal lwidth(0) barwidth(0.8)) ///
(///
, yscale(noline) ///
xlabel(`xlab', nogrid) ///
ylabel(1(1)18, nogrid noticks valuelabel labsize(2)) ///
ytitle("Stage") ///
legend(order(1 "Female" 2 "Male") size(2)) ///
title("{bf}Email Campaign Funnel", size(2.75)) ///
scheme(white_tableau)
命令运行结果见下图:
注意:文中范例代码所需数据需要从网页导入,如果在导入数据时遇到代理问题,可以将先进入网页查看数据,复制并保存到本地 \(.txt\) 或 \(.csv\) 文件,使用数据时直接从本地导入即可。 import delimited using "C:\Users\Lenovo\Desktop\抖动图数据.txt", delimiter(",") clear
6. 参考资料
- Data Envelopment Analysis (DEA) Visualization using Stata, -Link-
7. 相关推文
Note:产生如下推文列表的 Stata 命令为: lianxh 绘图 可视化, m
安装最新版 lianxh
命令: ssc install lianxh, replace
- 万莉, 2020, Stata绘图全解:绘图语法-条形图-箱型图-散点图-矩阵图-直方图-点图-饼图, 连享会 No.34.
- 万莉, 2021, Stata绘图:世行可视化案例-条形图-密度函数图-地图-断点回归图-散点图, 连享会 No.560.
- 万莉, 2021, Stata绘图:回归系数可视化-论文更出彩, 连享会 No.564.
- 万莉, 2020, Stata:读懂直方图, 连享会 No.479.
- 侯新烁, 2020, Stata绘图:一个干净整洁的-Stata绘图模板qlean, 连享会 No.354.
- 保瑞, 2021, Stata绘图-组间差异可视化:不良事件火山图、点阵图, 连享会 No.675.
- 刘东, 2023, Stata绘图:精美的散点图和线性拟合图-scatterfit-slopefit, 连享会 No.1251.
- 刘东, 2024, Stata:手动计算置信区间, 连享会 No.1498.
- 刘亮, 2020, Stata: 约翰霍普金斯大学 COVID-19 疫情数据处理及可视化, 连享会 No.107.
- 刘杨, 连玉君, 2020, Stata可视化:让他看懂我的结果!coefplot-arrowplot, 连享会 No.45.
- 刘潍嘉, 2023, Stata绘图:凹凸线图与凹凸面积图-bumparea-bumpline, 连享会 No.1308.
- 刘聪聪, 陈点点, 2020, Stata:interflex-交乘项该这么分析!, 连享会 No.121.
- 初虹, 2023, 值得收藏!三个Stata可视化绘图网站, 连享会 No.1220.
- 卢家锐, 连玉君, 2020, Stata绘图:用-bytwoway-实现快速分组绘图, 连享会 No.357.
- 史柯, 2022, Stata:绘制宏观时序图, 连享会 No.940.
- 吴小齐, 2024, Stata绘图:高级柱状图(二)-离散变量之间关系的可视化, 连享会 No.1469.
- 唐佳敏, 2022, Stata绘图:箱形图与小提琴图-vioplot, 连享会 No.855.
- 孙晓艺, 2024, Stata 绘图:世行研究员团队的可视化手册, 连享会 No.1437.
- 孙晓艺, 2024, Stata绘图大礼包:27个常用的可视化范例及代码, 连享会 No.1372.
- 孙法融, 2023, VOSviewer:文献分析软件介绍, 连享会 No.1267.
- 孙碧洋, 2020, Stata绘图:随机推断中的系数可视化, 连享会 No.471.
- 左祥太, 2021, Stata 绘图:用 Stata 绘制一打精美图片-schemes, 连享会 No.788.
- 左祥太, 2021, Stata可视化:biplot一图看尽方差、相关性和主成分, 连享会 No.814.
- 张伟广, 2020, Stata绘图:bgshade命令-在图形中加入经济周期阴影, 连享会 No.353.
- 张家星, 2023, Stata绘图:为图形选择优美的配色方案-color_style, 连享会 No.1160.
- 张弛, 2024, Stata 绘图:用 geoplot 绘制中国地图, 连享会 No.1401.
- 张蛟蛟, 2022, Stata绘图-可视化:组间差异比较散点图, 连享会 No.897.
- 张铭鑫, 2022, Stata绘图:circlepack-绘制圆堆图, 连享会 No.1135.
- 强皓凡, 2022, Stata绘图:绘制桑基图-sankey_plot, 连享会 No.949.
- 彭甲超, 2022, Stata绘图:绘制美观的散点图-superscatter, 连享会 No.959.
- 彭甲超, 2021, Stata:边际处理效应及其可视化-mtefe-T309, 连享会 No.128.
- 彭甲超, 2021, 常用科研统计绘图工具介绍, 连享会 No.750.
- 徐嘉树, 2019, Stata绘图:绘制单个变量的时序图, 连享会 No.102.
- 徐阳, 2021, Stata绘图:柱状图专题-T212, 连享会 No.625.
- 方森辉, 2022, Stata绘图:复现组间均值差异图, 连享会 No.1030.
- 朱志英, 2022, Stata:分仓散点图应用-binscatter, 连享会 No.1139.
- 李亭, 2022, Stata绘图:如何更高效的绘制图形, 连享会 No.954.
- 李其璋, 2023, Stata绘图:一套高效绘图命令-plottabs, 连享会 No.1213.
- 李原, 2024, Stata绘图:漏斗图-组间绩效比较可视化-funnelinst, 连享会 No.1373.
- 李胜胜, 2023, Stata绘图:balanceplot-图示组间差异和平衡性, 连享会 No.1236.
- 李胜胜, 2023, Stata绘图:balanceplot-系数可视化之平衡性点图, 连享会 No.1252.
- 李胜胜, 2023, Stata绘图:绘图模板介绍-cleanplots, 连享会 No.1173.
- 李青塬, 2022, Stata绘图:addplot-fabplot-多图层美化图片, 连享会 No.874.
- 杨学敏, 2021, 知乎热议:有哪些一用就爱上的可视化工具?, 连享会 No.664.
- 杨涵慧, 连玉君, 2024, Stata绘图:插图!子图!grinset, 连享会 No.1356.
- 林友晖, 2023, Stata绘图:相关系数可视化, 连享会 No.1205.
- 柯有聪, 2023, Stata绘图:正负异色柱形图-marimekko, 连享会 No.1232.
- 浦进博, 2024, Stata地图:geoboundary-轻松获取全球地图数据, 连享会 No.1527.
- 浦进博, 邓铨雄, 2024, Stata绘图:地图神器geoplot, 连享会 No.1383.
- 温世彬, 2022, Stata绘图:sunflower-向日葵图-克服散点重叠, 连享会 No.1013.
- 温凯迪, 2023, Stata绘图:散点与分组密度函数图, 连享会 No.1208.
- 王卓, 2024, Stata绘图:政治关联可视化, 连享会 No.1428.
- 王卓, 2024, Stata绘图:政治关联可视化-B612, 连享会 No.1427.
- 王胜文, 2022, Stata绘图:COVID-19数据可视化, 连享会 No.1099.
- 王鹏, 2020, Stata:图形美颜-自定义绘图模板-grstyle-palettes, 连享会 No.253.
- 甘月, 2022, Stata绘图:峰峦图绘制 joy_plot, 连享会 No.975.
- 籍保龙, 2024, Stata教程:绘图和可视化, 连享会 No.1388.
- 肖蕊, 2022, Stata可视化:能用图形就不用表格, 连享会 No.977.
- 苗妙, 2021, Stata绘图模板-极简风格:plotplain和plottig, 连享会 No.659.
- 苗妙, 2022, Stata绘图:山脊图绘制, 连享会 No.997.
- 范思妤, 2022, Stata绘图:环形柱状图-实时全球新冠确诊人数, 连享会 No.1000.
- 袁子晴, 2021, Stata绘图:addplot-层层叠加轻松绘图, 连享会 No.810.
- 袁子晴, 2021, Stata绘图:自定义绘图利器-palettes, 连享会 No.828.
- 袁子晴, 2021, forest-森林图:分组回归系数可视化, 连享会 No.651.
- 谢作翰, 2019, 普林斯顿Stata教程(二) - Stata绘图, 连享会 No.78.
- 谢佳松, 2022, Stata绘图:回归系数可视化-multicoefplot, 连享会 No.956.
- 谢佳松, 2022, Stata绘图:绘制华夫饼图-waffle, 连享会 No.960.
- 谢嘉伟, 2025, Stata 地图:cntraveltime-助你足不出户丈量中国, 连享会 No.1539.
- 谢嘉伟, 2024, Stata 绘图:binscatterhist-分仓散点图+直方图, 连享会 No.1506.
- 谢嘉伟, 2025, Stata:更适合中国的坐标命令-cngcode-cnaddress, 连享会 No.1549.
- 连享会, 2020, Stata 200 问:常见问题都在这里了-UCLA FAQs, 连享会 No.467.
- 连享会, 2020, Stata绘图:在图片中添加虚线网格线, 连享会 No.355.
- 连享会, 2020, Stata绘图:多维柱状图绘制, 连享会 No.273.
- 连享会, 2020, Stata绘图:绘制一颗红心-姑娘的生日礼物, 连享会 No.358.
- 连享会, 2020, Stata绘图:让图片透明——你不要掩盖我的光芒, 连享会 No.359.
- 连享会, 2022, 连享会主页-推文列表-按时间, 连享会 No.449.
- 连享会, 2022, 连享会主页-推文列表-按类别, 连享会 No.448.
- 连享会, 2024, 连享会公开课:实证分析可视化——6月30日-免费参与, 连享会 No.1411.
- 连玉君, 2024, Stata 绘图:图形中的中文和英文能否设定为不同的字体, 连享会 No.1335.
- 连玉君, 2020, Stata绘图:制作教学演示动态图-GIF, 连享会 No.351.
- 连玉君, 2022, Stata绘图:唯美的函数图-自定义水平附加线和竖直附加线, 连享会 No.1064.
- 连玉君, 2024, Stata绘图:如何调整图形的纵横比?, 连享会 No.1528.
- 连玉君, 2020, Stata绘图:怎么在Stata图形中附加水平线或竖直线?, 连享会 No.356.
- 连玉君, 2020, Stata绘图:用暂元统一改变图形中的字号, 连享会 No.274.
- 连玉君, 2020, Stata绘图:重新定义坐标轴刻度标签, 连享会 No.360.
- 连玉君, 2020, Stata黑白图形模板:中文期刊风格的纯黑白图形, 连享会 No.61.
- 连玉君, 2020, Stata:在线可视化模拟-OLS-的性质, 连享会 No.384.
- 连玉君, 许梦洁, 2020, Stata:系数为何不显著?GIF演示OLS的性质.md, 连享会 No.402.
- 邓浩然, 2020, Stata:图示交互效应-调节效应, 连享会 No.383.
- 邓鸿斌, 2021, 给你的图形化个妆:Stata绘图常用选项汇总-上篇, 连享会 No.629.
- 邓鸿斌, 2021, 给你的图形化个妆:Stata绘图常用选项汇总-下篇, 连享会 No.630.
- 郑宇, 2024, Stata绘图:加权直方图, 连享会 No.1425.
- 金振, 2022, Stata绘图:太美了!羊皮卷风格图形, 连享会 No.841.
- 陈佳慧, 2023, Stata绘图:mrtab-mrgraph-多元响应变量列表呈现和可视化, 连享会 No.1285.
- 陈佳慧, 2024, dgraph-组间均值差异t检验:列表及可视化, 连享会 No.1367.
- 陈凤, 2023, Stata绘图:spider-绘制蜘蛛网图-雷达图, 连享会 No.1178.
- 陈卓然, 2023, JF论文复现:金融学术圈的女性们, 连享会 No.1302.
- 陈卓然, 2022, Stata绘图:绘制二维地图和中国地图-geo2xy, 连享会 No.984.
- 陈卓然, 2023, 可重复研究:基于SCons构造文档结构和可视化图形-statacons, 连享会 No.1307.
- 陈振环, 张少鹏, 2021, Stata空间计量:莫兰指数绘图moranplot命令介绍, 连享会 No.729.
- 雷诺, 2023, Stata绘图:confcomptwp-二维系数的置信区间和可比区间可视化, 连享会 No.1257.
- 雷诺, 2023, Stata:二维估计的可视化-confcomptwo, 连享会 No.1305.
- 韩杰, 2022, Stata绘图:面板数据可视化-panelview, 连享会 No.1035.
- 颜国强, 2024, 相同的数据、不同的视角:可视化如何影响数据解读, 连享会 No.1503.
- 马洪栋, 2024, Stata绘图:高级柱状图(一)-均值和置信区间-cibar-coefpl, 连享会 No.1379.
- 马洪栋, 2024, Stata绘图:高级柱状图(三)-堆叠柱状图, 连享会 No.1413.
- 高娜娜, 2020, 数据可视化:带孩子们边玩边学吧, 连享会 No.426.
- 高瑜, 2024, eventbaseline:事件研究的估算与可视化, 连享会 No.1486.
- 高瑜, 2024, 事件研究和多期DID可视化新命令, 连享会 No.1507.