G3a. 直方图实例
作者:万莉 (北京航空航天大学)
邮箱:wanli_buaa@163.com
在实证结果可视化方面,直方图是一个重要的分析工具。无论是描述性分析阶段还是估计系数分析阶段,都可以借助直方图直观地呈现。
本推文将详细介绍绘制直方图的各种命令,结构安排如下:第一部分先简单介绍直方图的含义;第二部分着重介绍 Stata 里最基本的命令 histogram
;第三部分介绍一些好用的外部命令;最后讨论如何进一步美化图形。
1. 直方图简介
直方图 (histogram) 是用一系列宽度相等、高度不等的矩形表示数据分布的图。矩形的宽度表示数据范围的间隔,矩形的高度表示在给定间隔内数据出现的频数或频率。
直方图与条形图(柱状图)的区别:条形图用矩形宽度表示类别,且宽度都相等,而直方图用宽度表示组距,宽度可以不相等;条形图是分开排列的,而由于分组数据具有连续性,直方图是连续排列的(注:Stata 中也可以对离散变量进行绘直方图)。
Source: 柏满迎等.应用统计学:经济与管理中的数据分析[M].北京:清华大学出版社,2011:36.
2. 基本命令- histogram
本节将详细介绍 Stata 里绘制直方图的最基本命令 histogram
。本节结构为:介绍语法结构–绘制连续变量的基本直方图–绘制离散变量的基本直方图–展示两个完整的例子。
2.1 语法结构
执行 help histogram
可查看帮助文件。
其语法结构为:
histogram varname [if] [in] [weight] ///
. [, [continuous_opts | discrete_opts] options]
其中: - varname 是用于绘制图形的变量 - if 是设定样本范围的条件语句 - in 用于设定观察值范围 - weight 用于设定权重 - continuous_opts 是连续变量可用选项 - discrete_opts 是离散变量可用选项 - options 是连续、离散变量公用选项
histogram
的主要选项如下:
选项类别 | 具体命令 | 解释 |
---|---|---|
连续变量 | bin(#) |
设置矩形的数目为# |
连续变量 | width(#) |
设置矩形的宽度为# |
连续变量 | start(#) |
设置第一个矩形的起始数值# 默认值为观测值的最小值 |
离散变量 | discrete |
离散变量的直方图必须附加 discrete 选项 |
离散变量 | width(#) |
设置矩形的宽度为# |
离散变量 | start(#) |
设置第一个矩形的起始数值# 默认值为观测值的最小值 |
公用选项 | density |
按密度绘制直方图 为默认选项 |
公用选项 | fraction |
按比例绘制直方图 |
公用选项 | frequency |
按频数绘制直方图 |
公用选项 | percent |
按百分比绘制直方图 |
公用选项 | bar_options |
设定矩形细节的选项 |
公用选项 | binrescale |
结合 by() 命令时, 自动调节矩形的宽度 |
公用选项 | addlabels |
为矩形添加高度标签 |
公用选项 | addlabopts |
设定高度标签显示细节的选项 |
公用选项 | normal |
附加正态分布曲线 |
公用选项 | normopts() |
设定正态分布曲线细节 |
公用选项 | kdensity |
附加核密度函数曲线 |
公用选项 | kdenopts() |
设定核密度函数曲线细节 |
2.2 连续变量的直方图
本小节将介绍如何绘制连续变量的直方图。
sysuse nlsw88.dta, clear // 调用内置数据
.
histogram wage, ///
. note("注释:矩形的高度对应样本数占总样本的比例,总【面积】为 1")
histogram wage, fraction ///
. note("注释:将矩形的【高度】总和限制为 1")
histogram wage, percent ///
. note("注释:将矩形的【高度】总和限制为 100")
histogram wage, frequency ///
. note("注释:纵坐标为对应的样本数(频数),而非比例")
histogram wage, normal ///
. note("注释:附加正态分布曲线")
histogram wage, kdensity ///
. note("注释:附加核密度函数曲线")
histogram wage, addlabels ///
. addlabopts(mlabposition(12) mlabgap(3) ///
mlabangle(45) mlabsize(vsmall) mlabcolor(navy)) ///
note("注释:每个矩形上方附加一个表示其高度的数字" ///
"addlabopts(...)里的命令分别控制标签位置," ///
"与矩形间距,旋转角度,标签大小,颜色。")
help marker_label_options
.
histogram wage, by(race) binrescale
. graph save "$FIG\fig1-8-1.gph", replace
.
histogram wage, by(race) ///
. note("注释:利用 by(),按 race 变量进行分组")
histogram wage, bin(20) ///
. none) lcolor(black) ///
fcolor(///
lwidth(medium) lpattern(solid) note("注释:bin(#)指定分为几个组别" ///
"fcolor(...) 设定设定柱子的填充颜色。" ///
"lcolor(...) 设定矩形的轮廓颜色。" ///
"lwidth(...) 设定矩形的外边缘线的宽度。" ///
"lpattern(...) 设定矩形的外边缘线的类型。")
graph query linewidthstyle 列示线宽代号。
*可通过命令 palette linepalette 图示线型代号。
*可通过命令
*可通过外部命令 palette_all 查看颜色代号。ssc install full_palette 即可下载该外部命令。 *运行
命令运行结果如下图:
2.3 离散变量的直方图
本小节将介绍如何绘制离散变量的直方图。
sysuse nlsw88.dta, clear // 调用内置数据
.
histogram grade
. graph save d1, replace
. histogram grade, discrete //离散变量的直方图必须附加 discrete 选项
. graph save d2, replace
.
graph combine d1.gph d2.gph // 对比差异 .
命令运行结果如下图:
2.4 两个完整的例子
首先,我们先看第一个例子——利用 by(...)
进行分组绘制直方图。
sysuse auto, clear
.
histogram mpg, percent discrete ///
. by(foreign, col(1) note(分组指标:汽车产地) ///
title("图3:不同产地汽车里数") ///
subtitle("直方图")) ///
scheme(s1mono) gap(50) ///
ytitle(百分比(%)) xtitle(汽车里数) ///
xlabel(12(2)42)
graph save "fig3-1.gph", replace
. graph export "fig3-1.png", replace .
解释:
by(...)
里的命令分别为: 按 foreign 变量进行分组,图形按单列显示,设置注释,设置标题,设置副标题;scheme(...)
设定图形模板 (图形的配色、字号等会自动设定);gap(5)
:调节矩形之间的间隙,设置为5
。ytitle("Miles per Gallon", option)
:设置 y 轴标题为 “Miles per Gallon”。xtitle("Car Type", option)
:设置 x 轴标题为 “Car Type”。xlabel(12(2)42, option)
:设置横坐标的刻度标签,从 12 到 42,每隔 2 个刻度。title("Fuel Efficiency by Car Type", option)
:设置主标题。subtitle("Comparison of MPG for Foreign and Domestic Cars", option)
:设置副标题。scheme(s1mono)
:使用 Stata 默认的黑白配色方案。
第二个例子利用多种绘图选项,绘制了较为复杂的直方图。
sysuse sp500, clear
. summarize volume // 基本统计量
.
#delimit ;histogram volume, freq normal
. color(white))
graphregion(addlabels addlabopts(mlabcolor(g))
xaxis(1 2)ylabel(0(10)65, grid)
xlabel( 12321 "mean"
"-1 s.d."
9735 "+1 s.d."
14907 "-2 s.d."
7149 "+2 s.d."
17493 "+3 s.d."
20078 "+4 s.d."
22664 grid)
,axis(2) ebg) lcolor(gs8)
fcolor(black))
lwidth(medium) normopts(lcolor(subtitle("图4: S&P 500 交易量 (2001年1月-12月)")
ytitle(频数)
xtitle("交易量(千笔)") xscale(titlegap(2))
xtitle("", axis(2))
note("数据来源:雅虎!财经数据") ;
cr
#delimit
graph save "fig3-2.gph", replace
. graph export "fig3-2.png", replace .
说明如下:
graphregion(color(...))
:设置图形背景的颜色。
xaxis(1 2)
:设置双坐标 x 轴。
xlabel(..., axis(2) grid gmax)
:设置 x 轴标签及刻度,其中axis(2)
表示第二个 x 轴,grid
添加网格线,gmax
表示最大值。
normopts(lcolor(black))
:设置正态分布曲线的颜色为黑色。
xscale(titlegap(2))
:设置 x 轴与 x 轴标题之间的间距。
相关帮助文件:
help axis_choice_options
([G-3] axis choice options)help axis_label_options
([G-3] axis label options)
上述两个例子的运行结果,如下图:
3. 好用的外部命令
本小节将介绍 8 个有用的外部命令。
3.1 命令1:histbox
命令 histbox
能同时绘制 直方图 和 箱型图。
ssc install histbox, replace //下载外部命令
. help histbox //generate histogram with boxplot
.
sysuse auto, clear //调用内置数据
.
#d ;mean freq normal bin(10)
histbox mpg, title("汽车里数分布")
xlabel(12(2)42);
cr
#d
/*注意:
该命令默认按比例 (fraction) 绘制直方图,
若加上 freq 则是按频数绘制直方图;
不能用 by 选项进行分组绘图。
*/
3.2 命令2:historaj
命令 historaj
在基本直方图上添加了描述性统计。
ssc install historaj, replace //下载外部命令
. help historaj //histogram with descriptive statistics
.
sysuse auto, clear
.
. historaj mpg/*注意:
该命令不能用 by 选项进行分组绘图;
执行命令后需要手动在界面进行设置。
*/
3.3 命令3:histoflogx
命令 histoflogx
在绘制直方图时,把横轴改为对数坐标。
replace //下载外部命令
. net install histoflogx, findit histoflogx
* 不能下载,可以用 help histoflogx //Histogram with log scale on the x-axis
.
sysuse auto, clear
. bin(9) ///
. histoflogx mpg, percent start(`=log(10)') ///
lab(10/20 30 40)
3.4 命令4:eqprhistogram
命令 eqprhistogram
使得每个矩形的面积相等。比如,令直方图有 10 个矩形,则可以看出数据十分位数 (Quartile) 的分布情况。
ssc install eqprhistogram, replace //下载外部命令
. help eqprhistogram //equal probability histogram
.
sysuse auto, clear
.
///
. eqprhistogram price, bin(10) plot(kdensity price)
3.5 命令 5:spechist
命令 spechist
可选用不同方法确定矩形的个数/宽度。
ssc install spechist, replace //下载外部命令
. help spechist //可选用不同方法确定矩形的个数/宽度
.
sysuse citytemp, clear
. all) ///
spechist tempjuly, me(imargin(small))
kden copt( * 画出所有方法对应的图形
3.6 命令6:marhis
命令 marhis
可用于分析边际效应。注意该命令仅适用于分析以下三种变量: (1) 任意连续变量; (2) 两个连续变量的交乘项; (3) 连续变量和类别变量的交乘项; 注意:交乘项必须使用因子变量的语法格式。
. ssc install marhis, replace //下载外部命令
. help marhis
* to produce predictive margins and
* marginal effects plots with histogram
* after regress, logit, xtmixed and mixed
. sysuse "nlsw88.dta", clear
reg wage i.industry c.hours##i.union
marhis hours, cate(union) // 连续变量和类别变量的交乘项
关于 边际效应 的详细介绍,可参如下推文:
- 江鑫, 2021, Stata:边际效应知多少?f_able命令(上), 连享会 No.689.
- 江鑫, 2021, Stata:边际效应知多少?f_able命令(下), 连享会 No.690.
- 连玉君, 杨柳, 2020, Stata: 边际效应分析, 连享会 No.64.
- 陈贤孟, 2022, 解读交互项及其边际效应, 连享会 No.1075.
3.7 命令7:bihist
命令 bihist
可以用来绘制双变量双向直方图。
ssc install bihist, replace //下载外部命令
. help bihist
.
sysuse nlsw88, clear
.
by(married) ///
. bihist wage, tw(color(navy)) ///
color(maroon))
tw1(/*
by(married): 以婚姻状态 (married) 分组,绘制工资 (wage) 的双向直方图。
tw(color(...)) tw1(color(...)): 分别设置上下矩形的颜色。
*/
3.8 命令 8:byhist
命令 byhist
可以用来绘制双变量单向直方图。
ssc install byhist //下载外部命令
. help byhist
.
sysuse nlsw88, clear
. by(married) ///
. byhist wage, color(navy)) ///
tw1(color(maroon))
tw2(/*
by(married): 以婚姻状态 (married) 分组,绘制工资 (wage) 的单向直方图。
tw1(color(...)) tw2(color(...)): 分别设置左右矩形的颜色。
*/
![Figure 11]!(https://fig-lianxh.oss-cn-shenzhen.aliyuncs.com/aHR0cHM6Ly91cGxvYWQtaW1hZ2VzLmppYW5zaHUuaW8vdXBsb2FkX2ltYWdlcy8xODM3ODkzOC04NjEzMjkxMDVjYjZmOGMxLnBuZw)
4. 进一步美化图形
4.1 如何呈现透明的直方图
在多个图形重叠出现时,设定图形的透明度非常实用。举个例子,假设你在绘制两个变量的直方图时,发现两个直方图有重叠部分,该怎么办呢?
如果我们不设定透明度,直接绘制两个直方图,则图形显示如下:
sysuse "nlsw88.dta", clear
.
#d ;twoway (hist wage if union==0,
. color(eltgreen))
frac hist wage if union==1,
(color(eltblue)),
frac legend(label(1 "union") label(2 "Non-union"))
title("错误示范") ;
cr #d
你会发现上例呈现的图形很丑,蓝色直方图几乎覆盖了下方浅绿色直方图。为了得到更好的图片呈现效果,我们可以设定颜色的透明度。这可以通过两个方法来实现。
第一种方法 是,通过选项 fcolor(none)
设定颜色的透明度。
#d ;twoway (hist wage if union==0,
.
frac lcolor(gs12) fcolor(gs12)) hist wage if union==1,
(none) lcolor(black)),
frac fcolor(legend(label(1 "union") label(2 "Non-union"))
title("第一种方法");
cr
#d /*
fcolor(...) 设定矩形的填充颜色。
fcolor(none) 表示无填充颜色。
lcolor(...) 设定矩形的轮廓颜色。
*/
第二种方法是,通过选项 color(...%#)
设定颜色的透明度。 注意该选项仅适用于 Stata 15 及以上版本。
sysuse "nlsw88.dta", clear
.
#d ; twoway (hist wage if union==1,
black*0.3)
frac fcolor(red*0.3%100))
lcolor(hist wage if union==0,
(color(green%40)
frac black)),
lcolor(legend(label(1 "union") label(2 "Non-union"))
title("第二种方法");
cr
#d /*
color(color%#), # 的数值越小,透明度越高。
fcolor(...) 设定矩形的填充颜色。
lcolor(...) 设定矩形的轮廓颜色。
*/
4.2 如何在同一幅图绘制多个垂直直方图
本小节的灵感源自一个知乎问题:想知道这种类型的图是用什么计量软件做出来的?。本小节的代码虽然不能完全解决这个问题,但希望能提供一些思路,供大家参考和指正。
由于没有该问题的原始数据,故使用 Stata 软件自带的数据文件 nlsw88.dta
进行模拟。该数据包含了 1988 年采集的 2246 个美国妇女的资料。 本小节将针对 种族 race、职业 industry 两个变量进行绘图。
ssc install mdesc //下载外部命令
. sysuse "nlsw88.dta", clear
.
keep industry race
. labelbook //查看文字-变量对应表
. /*
人种:
1 white
2 black
3 other
行业:
1 Ag/Forestry/Fisheries
2 Mining
3 Construction
4 Manufacturing
5 Transport/Comm/Utility
6 Wholesale/Retail Trade
7 Finance/Ins/Real Estate
8 Business/Repair Svc
9 Personal Services
10 Entertainment/Rec Svc
11 Professional Services
12 Public Administration
*/
//检查变量是否有缺失值
mdesc drop if industry == .
bysort race industry: gen n_race_ind = _N
bysort race: gen n_race = _N
duplicates drop race industry, force
gen ratio = n_race_ind/n_race
// 分人种后,计算每个行业的占比
sort race industry
// 发现人种为黑人和其他时,有的行业缺失
// 补上缺失行业,便于画图时共用 y 轴
drop n_*
save temp.dta, replace
replace race = 2 in 1
replace industry = 2 in 1
replace race = 3 in 2
replace industry = 1 in 2
replace race = 3 in 3
replace industry = 2 in 3
replace race = 3 in 4
replace industry = 6 in 4
replace race = 3 in 5
replace industry = 10 in 5
keep in 1/5
replace ratio = 0
append using "temp.dta"
sort race industry
erase temp.dta
*-第一个直方图的辅助图graph hbar ratio if race == 1, ///
. over(industry, ///
label(grid glpattern(dash))) ///
ylabel(,nolabels grid glpattern(dash)) ///
ytitle("race: white", placement(left)) ///
saving(fig_11.gph, replace)
*-第一个直方图graph hbar ratio if race == 1, ///
. over(industry, ///
label(nolabels grid glpattern(dash))) ///
ylabel(,nolabels grid glpattern(dash)) ///
ytitle("race: white", placement(left)) ///
saving(fig_12.gph, replace)
*-第二个直方图graph hbar ratio if race == 2, ///
. over(industry, ///
label(nolabels grid glpattern(dash))) ///
ylabel(, nolabels grid glpattern(dash)) ///
ytitle("race: black", placement(left)) ///
saving(fig_2.gph, replace)
*-第三个直方图graph hbar ratio if race == 3, ///
. over(industry, ///
label(nolabels grid glpattern(dash))) ///
ylabel(,nolabels grid glpattern(dash)) ///
ytitle("race: others", placement(left)) ///
saving(fig_3.gph, replace)
*-图形合并graph combine fig_11.gph fig_12.gph ///
. ///
fig_2.gph fig_3.gph, imargin(zero) col(4) iscale(*0.8)
此时图形还并不完美,需要借助 graph editor 手动编辑,如下图所示:
锵锵锵, 最后成果图如下:
5. 其它相关命令
help tabplot
// SJ 16(2): 491–510 外部命令安装:ssc install tabplot, replace
help hist2
// Histograms with more options 外部命令安装:net install hist2, replace
help marginsplot
// 分析边际效应help twoway__histogram_gen
// 具体介绍参见 SJ 5(2):280–281
6. 扩展阅读
- How can I get a histogram with varying bin widths?
- How can I combine a histogram and a boxplot in Stata?
- A code fragment for combining a histogram and boxplot in one graph | Stata Code Fragments
- Overlaying histograms in Stata
7. 相关推文
Note:产生如下推文列表的 Stata 命令为:
lianxh 直方图 长条图 密度函数, md0 nocat
安装最新版lianxh
命令:
ssc install lianxh, replace
- 万莉, 2020, Stata绘图全解:绘图语法-条形图-箱型图-散点图-矩阵图-直方图-点图-饼图, 连享会 No.34.
- 万莉, 2021, Stata绘图:世行可视化案例-条形图-密度函数图-地图-断点回归图-散点图, 连享会 No.560.
- 万莉, 2020, Stata:读懂直方图, 连享会 No.479.
- 刘欣妍, 史柯, 2022, Stata:描述性统计分析新命令-dstat, 连享会 No.926.
- 吴俊樊, 2022, Stata:双变量联合核密度函数图-kdens2, 连享会 No.858.
- 吴俊樊, 2022, Stata:多个核密度函数图叠加-mkdensity, 连享会 No.859.
- 孙晓艺, 2024, Stata绘图大礼包:27个常用的可视化范例及代码, 连享会 No.1372.
- 汪京, 2024, multihistogram-多变量直方图, 连享会 No.1457.
- 温凯迪, 2023, Stata绘图:散点与分组密度函数图, 连享会 No.1208.
- 袁子晴, 2021, 史上最牛Stata绘图模板-schemepack:酷似R中的ggplot2, 连享会 No.819.
- 谢嘉伟, 2024, Stata 绘图:binscatterhist-分仓散点图+直方图, 连享会 No.1506.
- 连玉君, 2022, Stata绘图:唯美的函数图-自定义水平附加线和竖直附加线, 连享会 No.1064.
- 郑宇, 2024, Stata绘图:加权直方图, 连享会 No.1425.
- 颜国强, 2024, 相同的数据、不同的视角:可视化如何影响数据解读, 连享会 No.1503.