查看原文
其他

Stata绘图:绘制桑基图-sankey_plot

连享会 连享会 2023-10-24

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

连享会 · 效率分析专题

作者:强皓凡 (复旦大学)
邮箱:hfqiang21@m.fudan.edu.cn


目录

  • 1. 什么是桑基图

  • 2. sankey_plot 命令介绍

  • 3. 实例演示

    • 3.1 大陆间移民

    • 3.2 就业市场流动

    • 3.3 宠物、婚姻和幸福

  • 4. 相关推文



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

1. 什么是桑基图

根据百度百科的定义,桑基图 (Sankey diagram),即桑基能量分流图,也叫桑基能量平衡图。它是一种特定类型的流程图,图中延伸的分支的宽度对应数据流量的大小,通常应用于能源、材料成分、金融等数据的可视化分析。因 1898 年 Matthew Henry Phineas Riall Sankey 绘制的 “蒸汽机的能源效率图” 而闻名,此后便以其名字命名为 “桑基图”。

桑基图最明显的特征就是,始末端的分支宽度总和相等,即所有主支宽度的总和应与所有分出去的分支宽度的总和相等,保持能量平衡。本文将着重分享使用 Stata 中的 sankey_plot 命令来制作桑基图的过程。

2. sankey_plot 命令介绍

sankey_plot 命令安装:

net describe http://repec.org/bocode/s/sankey_plot
net install sankey_plot, replace
net get sankey_plot, replace // 获取数据和范例
ssc install palettes, replace
ssc install colrspace, replace

sankey_plot 命令语法:

sankey_plot x0 y0 x1 y1 [if] [in] [, sankey_options twoway_options]

其中,Sankey 坐标选项:

  • x0 y0 x1 y1 :必需参数,提供了要绘制的坐标和分组。(x0, y0) 表示原点,(x1 , y1) 表示终点。该值标识节点。X0 和 x1 必须是数值,y0 和 y1 可以是数字或字符串,但不能两者都是。如果它们是字符串,这些值将被用作标签来识别节点;
  • width0(varname):提供一个具有原点 (x0, y0) 的权值或宽度的变量,默认是 0.01;
  • width1(varname):在目标 (x1,y1) 处提供一个具有权值或宽度的变量,默认值是 width0 中的值。

Sankey 外观选项:

  • sharp(#):使用 # 定义更改连接段或链接的外观,默认是 7,必须大于 0,值为 1 时产生一条直线;
  • adjust:调整 Y 轴坐标以避免节点之间的重叠。请注意,调整后的节点位置仍将保持在原始值的 “附近”;
  • extra:基于 width0 和/或 width1 调整  Y坐标。有了这个选项,节点之间就不会有重叠。可以与 adjust 结合使用,得到更美观的结果;
  • gap(#):与 extra 一起使用。当使用 extra 时,请求在同一级别的节点之间添加一个 “间隙”;
  • noline:请求在没有边框的情况下绘制流线;
  • nobar:请求不绘制连接流线的节点块,即后文实例1中每个节点标签处突出显示的色块。

Sankey bar 和 label 选项:

  • bwidth(#):如果连接流线的节点块 (Bar) 被保留,这可以用来修改其宽度,0.025 为默认值;
  • bheight(#):当使用时,这将修改所有连接流线的节点块 (Bar) 的高度,默认是使用链接总和的高度;
  • bcolor(colorstyle):使用时,可以修改连接流线的节点块 (Bar) 的颜色;
  • label0(varname):给起点坐标打上标签,必须为字符串格式,无默认值,如果 y0 和 y1 是字符串,则不需要;
  • label1(varname):给终点坐标打上标签,必须为字符串格式,如果有,则默认为 label0。如果 y0 和 y1 是字符串,则不需要;
  • labangle(#):当提供了 lable0 时,可以使用这个选项修改标签的角度,默认值为 0;
  • labpos(#):当提供了 lable0 时,可以使用这个选项修改标签的位置。默认是将标签放置在第一级的右边,最后一级的左边;
  • labsize(#):当提供了 lable0 时,可以使用这个选项修改标签文本的大小;
  • labcolor(colorstyle):当提供了 lable0,或者 y0、y1 是字符串时,可以使用这个选项修改标签文本的颜色。

Sankey 颜色/样式选项:

  • pstyle(varname):可以提供一个变量,预先分配样式给特定的片段;
  • color(varname):可以提供一个变量,为特定的连接预先分配颜色,不能与 bcolor fillcolor 选项结合使用;
  • fillcolor(color):可以使用此选项为所有连接定义单一的某种颜色;
  • colorpalette(options):这个选项允许使用 Ben Jann 的 colorpalette,且大多数配色选项都是允许的。但是,透明度选项 opacity() 只会影响连接的流线的透明度深浅,而不会影响连接流线的节点块 (Bar)。

Sankey 实验性选项:

  • wide:这是一个实验性的选择。当数据中的每个变量对应于不同的水平级别时,可以使用它;
  • width(varname):如果使用了 wide 选项,则应该使用该选项定义每个流的权重;
  • tight:如果使用了 wide 选项,则该选项会 “压缩” 类别,以避免来自相同节点的多个流分开出现。

接下来,我们对 sankey_plot 命令进行一些概括描述。sankey_plot 是一个旨在促进在 Stata 中创建 Sankey 图的模块。此命令不进行任何数据处理,并假定数据已准备好。

桑基图的核心就是成对的连接坐标:从 (x0, y0) 到 (x1, y1)。这些点与宽度与 width0width1 成比例的流相连。x0 和 x1 标识绘图的垂直水平,这些变量必须是数字。y0 和 y1 标识级别内的不同组。这些变量可以是字符串的数字,但不能同时是两者。使用字符串变量时,这些值将用作级别内不同组的标签。

调整坐标有两个主要选项:

  • adjust:调整坐标,使组内的流没有重叠;
  • extra:根据 width0width1 调整坐标,使组之间没有重叠。

该命令还允许用户使用命令 colorpalatte 从不同的调色板中进行选择,仅在正确安装时可用。

3. 实例演示

3.1 大陆间移民

在本节,我们将使用 immigration.dta 依次绘制不同样式的桑基图。immigration.dta 数据为跨大陆移民流动的数据,包含 5 个变量,具体如下:

. use immigration, clear
. list in 1/10

+-------------------------------------------------+
| from to value x0 x1 |
|-------------------------------------------------|
1. | Africa Africa 3.14247 1 2 |
2. | East Asia East Asia 1.631 1 2 |
3. | South Asia East Asia .525881 1 2 |
4. | South East Asia East Asia .145264 1 2 |
5. | Africa Europe 2.10788 1 2 |
|-------------------------------------------------|
6. | East Asia Europe .601265 1 2 |
7. | Europe Europe 2.40148 1 2 |
8. | Latin America Europe 1.76259 1 2 |
9. | North America Europe 1.21593 1 2 |
10. | Oceania Europe .17037 1 2 |
+-------------------------------------------------+

首先,绘制最简单版本的桑基图。在以下命令中,x0x1 分别为代表起点和终点的两个数值,而 fromto 则是两个字符串变量,会在绘图时被用作标签。此时绘制的桑基图,只能为读者呈现各个起始点、终止点及彼此间是否有联系的简单信息。

. sankey_plot x0 from x1 to

接下来,我们可以通过 width0 来调整两端连线的宽度,这里设置为默认值 0.01 的 10 倍,即 0.1。

. gen w0 = 0.1
. sankey_plot x0 from x1 to, width0(w0)

当一个终点与多个起点之间发生连接时,会出现肉眼不易识别的交叠现象。为此,可以使用 adjust 选项来避免交叠问题。

. sankey_plot x0 from x1 to, width0(w0) adjust

如果不人为地设置线宽,而是使用本身的流量值 value 来作为线宽,那么所有的流线都会出现交叠,出现严重的无法阅读信息的问题。

. sankey_plot x0 from x1 to, width0(value)

在使用 value 流量值做线宽的情形下,即便使用 adjust 也无法解决可读性问题。

. sankey_plot x0 from x1 to, width0(value) adjust

有一种对上述问题进行边际改进的方法,即使用 extra 来调整坐标位置。

. sankey_plot x0 from x1 to, width0(value) extra

如果在使用 extra 的同时,也使用 adjust,则可进一步改进桑基图的可读性。

. sankey_plot x0 from x1 to, width0(value) extra adjust

接着,可以调整配色方案,便于读者阅读,比如使用全灰色的配色 fillcolor(gs12)

. sankey_plot x0 from x1 to, width0(value) extra adjust fillcolor(gs12)

或者,也可以调整其透明度 fillcolor(%50)

. sankey_plot x0 from x1 to, width0(value) extra adjust fillcolor(%50)

还可以增加节点之间的空隙,比如使用 gap(0.1)

. sankey_plot x0 from x1 to, width0(value) extra adjust fillcolor(%50) gap(0.1)

或许你不满意于默认的配色方案,那么可以使用 colorpalette() 来调配。例如,本例中还使用了透明度调整和不加流线的外框线的设置,来展现更为清晰的流线走向。其中,opacity() 取值为0-100,0 为完全透明,100 为完全不透明。

. sankey_plot x0 from x1 to, width0(value) extra adjust colorpalette(viridis, opacity(40)) gap(0.1) noline

还可以增加两端节点的名称,使用 xlabel() 来加以标注。

. sankey_plot x0 from x1 to, width0(value) extra adjust colorpalette(viridis, opacity(40)) ///
> gap(0.1) noline xlabel(1 "Source" 2 "Destination", nogrid)

更改一种配色方案、透明度和节点间距。

. sankey_plot x0 from x1 to, width0(value) extra adjust colorpalette(economist, opacity(30)) ///
> gap(0.15) noline xlabel(1 "Source" 2 "Destination", nogrid)

最后,可以加入图表题 title() 和注释内容 note()

. sankey_plot x0 from x1 to, width0(value) extra adjust colorpalette(HSV intense,opacity(40)) ///
> gap(0.1) noline xlabel(1 "Source" 2 "Destination", nogrid) title("Migration flows") ///
> note("Note: Abel, Guy J (2017) Estimates of Global Bilater tion Flows by Gender between 1960 and 2015")

3.2 就业市场流动

在本节,我们将使用 jobmarket.dta 数据依次绘制不同样式的桑基图。本数据集是就业市场数据,包含数周内就业市场流动的情况,包含 7 个变量,具体如下:

. use jobmarket, clear
. list in 1/10

+----------------------------------------------------------------------------------+
| y0 y1 week0 week1 label0 label1 candid~s |
|----------------------------------------------------------------------------------|
1. | 1 1 0 1 Jobs Applied to 32 Replies 15 15 |
2. | 1 2 0 1 Jobs Applied to 32 Rejections 5 5 |
3. | 1 3 0 1 Jobs Applied to 32 No Reply 12 12 |
4. | 1 1 1 2 Replies 15 Initial Interviews 9 9 |
5. | 1 2 1 2 Replies 15 Replied too late 6 6 |
|----------------------------------------------------------------------------------|
6. | 1 1 2 3 Initial Interviews 9 Task Requested 4 4 |
7. | 1 2 2 3 Initial Interviews 9 No Task Required 1 1 |
8. | 1 3 2 3 Initial Interviews 9 Rejected by me 2 2 |
9. | 1 4 2 3 Initial Interviews 9 Rejections 2 2 |
1. | 1 1 3 4 Task Requested 4 Final Interview 5 4 |
+----------------------------------------------------------------------------------+

首先做出最基本的桑基图,反映每周之间的变化情况。

. sankey_plot week0 y0 week1 y1

若想保持与上面相同的形状,但使用提供的宽度,则可以重新调整 Y0 和 Y1 坐标。

. gen y00=y0*10
. gen y11=y1*10
. sankey_plot week0 y00 week1 y11, width0(candidates) adjust

接下来,可以调整颜色、标签和轴坐标。

. sankey_plot week0 y00 week1 y11, width0(candidates) adjust xlabel(0 " " 1 "Week 1" 2 ///
> "Week 2" 3 "Week 3" 4 "Week 4" 5 "Week 5" 6 "Week 6", nogrid) fillcolor(gs12%50) ///
> label0(label0) label1(label1) xsize(10) ysize(6)

最后,使用 extra 命令调整节点的位置,使图形更为紧凑。

. sankey_plot week0 y00 week1 y11, width0(candidates) adjust extra xlabel(0 " " 1 ///
> "Week 1" 2 "Week 2" 3 "Week 3" 4 "Week 4" 5 "Week 5" 6 "Week 6", nogrid) ///
> fillcolor(gs12%50) label0(label0) label1(label1) xsize(10) ysize(6)

3.3 宠物、婚姻和幸福

在本节,我们将使用 dogs_and_happiness.dta 依次绘制不同样式的桑基图。本数据具有与上述内容不同的结构,没有使用一对一的坐标,而是使用变量来识别跨节点的流,这需要稍微不同的语法。本数据集包含 4 个变量,具体如下:

. use dogs_and_happiness, clear
. list

+------------------------------------------+
| married pet happy freq |
|------------------------------------------|
1. | Married:Yes Pet:Yes Happy:Yes 5 |
2. | Married:Yes Pet:Yes Happy:Yes 4 |
3. | Married:Yes Pet:No Happy:Yes 3 |
4. | Married:No Pet:Yes Happy:Yes 2 |
5. | Married:No Pet:No Happy:No 1 |
+------------------------------------------+

首先,绘制最基本的桑基图,请注意我们此时拥有三个节点,而非两个。

. sankey_plot married pet happy, wide width(freq)

接着,我们调整颜色和节点间距,并且去掉轴坐标。

. sankey_plot married pet happy , wide width(freq) fillcolor(%50) xlabel("", nogrid) gap(0.1)

最后,注意到有 2 组同时连接着 MarriedPetHappy,故而可以使用 tight 命令加以合并,并且添加主标题 title() 、副标题 subtitle() 和注释 note() 等内容。

. sankey_plot married pet happy , wide width(freq) fillcolor(%50) xlabel("",nogrid) ///
> gap(0.1) tight title("The Secret to Happyness") subtitle("Have Pets: Nora and Bruce!") ///
> note("Nora and Bruce belong to my wife and I")

4. 相关推文

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

  • 专题:Stata绘图
    • Stata绘图-可视化:组间差异比较散点图
    • Stata绘图:addplot-fabplot-多图层美化图片
    • Stata绘图:箱形图与小提琴图-vioplot
    • Stata绘图:太美了!羊皮卷风格图形
    • Stata绘图:自定义绘图利器-palettes
    • 史上最牛Stata绘图模版-schemepack:酷似R中的ggplot2-袁子晴
    • 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 站」,「面板数据」,「公开课」 等关键词细化搜索。


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

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