Stata 绘制双类别对比热力图

在数据可视化项目中,热力图通过指定每个颜色映射的规则,可以形象展示数据的分布信息。本篇将为大家介绍一个非常实用且简洁的双类别对比热力图,在研究及工作中都能广泛应用。

先来展示一下我们想要画出的图表:

整理数据

该案例选用 Stata 自带的 nlsw88 数据:

sysuse nlsw88, clear
tab grade

把 grade 小于 8 的都更改为 8 并生成一个新变量 g 存储:

gen g = max(grade, 8)
label var g "受教育年限"

把婚姻状态变量重命名为 m:

ren married m

计算每个受教育年限下不同婚姻状态的平均薪酬:

collapse wage, by(g m)

根据 wage 的值生成颜色值:

gen w = round(wage, 0.01)
sum wage, meanonly
gen c = round((wage - r(min))/(r(max) - r(min)) * 255)

生成需要的变量及颜色值后,接下来就是绘图了,这里采用循环函数设置不同工资值的颜色。

绘图展示

根据 c 值的大小生成 RGB 颜色值,随着 c 值的增加,B(蓝色)值增加,R(红色)和 G(绿色)同步降低(实际上就是黄色值降低),所以最后会得到一个黄蓝的渐变:

local cmd = "tw"
levelsof c, local(cs)
foreach i in `cs' {
local c1 = 120 + round(`i'/2)
local c2 = 255 - round(`i'/2)
local cmd = `"`cmd' (sc m g if c == `i', mc("`c2' `c2' `c1'") msize(ehuge) m(S))"'
}

`cmd'

图的雏形出来后,继续添加散点标签及调整其他选项:

* 添加散点标签
local cmd = `"`cmd' (sc m g, m(i) mlab(w) mlabpos(0))"'
`cmd', leg(off) yla(-0.75 " " 0 "未婚" 1 "已婚" 1.75 " ", notick nogrid) ///
xla(7 " " 8/18 19 " ", notick nogrid) plotr(margin(zero)) ///
yti("婚姻状态") ti("婚姻状态、受教育年限与工资水平的关系") ///
subti("绘制:微信公众号 RStata")
gr export pic1.png, width(2400) replace

拓展延伸 1

进一步就可以根据自己的需要更改渐变方案了,例如红色到蓝色的渐变(绿色为 0)。

* 红色到蓝色渐变
local cmd = "tw"
levelsof c, local(cs)
foreach i in `cs' {
local c1 = 120 + round(`i'/2)
local c2 = 255 - round(`i'/2)
local cmd = `"`cmd' (sc m g if c == `i', mc("`c2' 0 `c1'") msize(ehuge) m(S))"'
}

* 添加散点标签
local cmd = `"`cmd' (sc m g, m(i) mlab(w) mlabpos(0) mlabc(black))"'
di `"`cmd'"'
`cmd', leg(off) yla(-0.75 " " 0 "未婚" 1 "已婚" 1.75 " ", notick nogrid) ///
xla(7 " " 8/18 19 " ", notick nogrid) plotr(margin(zero)) ///
yti("婚姻状态") ti("婚姻状态、受教育年限与工资水平的关系") ///
subti("绘制:微信公众号 RStata")
gr export pic2.png, width(2400) replace

拓展延伸 2

也可以自己选定颜色(需要 22 种渐变色),颜色选择可以参考https://tidyfriday.cn/colors/#。

生成需要的变量:

sysuse nlsw88, clear
tab grade
gen g = max(grade, 8)
label var g "受教育年限"
ren married m
collapse (mean) wage, by(g m)
gsort -wage
gen w = round(wage, 0.01)

根据 wage 的大小生成 color 变量:

gen color = ""
local colorlist = `""44 25 76" "43 35 86" "40 46 96" "40 56 107" "39 67 118" "38 78 130" "39 88 142" "45 97 157" "51 103 171" "60 111 185" "69 118 193" "77 123 195" "85 129 192" "94 135 190" "103 141 188" "111 146 184" "120 152 182" "129 159 180" "138 165 177" "146 170 174" "156 176 171" "165 183 168""'
forval i = 1/22 {
local c: word `i' of `colorlist'
replace color = `"`c'"' in `i'
}

然后就可以绘图了:

local cmd = "tw"
forval j = 1/22 {
local cmd = `"`cmd' (sc m g in `j', mc("`=color[`j']'") msize(ehuge) m(S))"'
}

* 添加散点标签
local cmd = `"`cmd' (sc m g, m(i) mlab(w) mlabpos(0) mlabc(white))"'
di `"`cmd'"'
`cmd', leg(off) yla(-0.75 " " 0 "未婚" 1 "已婚" 1.75 " ", notick nogrid) ///
xla(7 " " 8/18 19 " ", notick nogrid) plotr(margin(zero)) ///
yti("婚姻状态") ti("婚姻状态、受教育年限与工资水平的关系") ///
subti("绘制:微信公众号 RStata")
gr export pic3.png, width(2400) replace

拓展延伸 3

另外也可以选用turku 调色板,其代码和拓展延伸 2 相似:

local colorlist = `""56 54 50" "65 63 56" "73 70 60" "82 78 66" "91 87 71" "100 95 76" "108 102 79" "118 111 84" "128 120 90" "138 127 94" "149 136 99" "161 144 106" "173 151 112" "184 154 117" "195 157 122" "204 160 128" "212 159 133" "220 160 137" "228 162 144" "237 166 153" "244 171 164" "249 179 176""'
forval i = 1/22 {
local c: word `i' of `colorlist'
replace color = `"`c'"' in `i'
}

* 绘图
local cmd = "tw"
forval j = 1/22 {
local cmd = `"`cmd' (sc m g in `j', mc("`=color[`j']'") msize(ehuge) m(S))"'
}

* 添加散点标签
local cmd = `"`cmd' (sc m g, m(i) mlab(w) mlabpos(0) mlabc(white))"'
di `"`cmd'"'
`cmd', leg(off) yla(-0.75 " " 0 "未婚" 1 "已婚" 1.75 " ", notick nogrid) ///
xla(7 " " 8/18 19 " ", notick nogrid) plotr(margin(zero)) ///
yti("婚姻状态") ti("婚姻状态、受教育年限与工资水平的关系") ///
subti("绘制:微信公众号 RStata")
gr export pic4.png, width(2400) replace

点击这里跳转到 RStata 短书平台获取附件:Stata 绘制双类别对比热力图

评论