桑基图(Sankey diagram),即桑基能量分流图,也叫桑基能量平衡图。它是一种特定类型的流程图,图中延伸的分支的宽度对应数据流量的大小,通常应用于能源、材料成分、金融、生物信息等数据的可视化分析。因1898年Matthew Henry Phineas Riall Sankey绘制的“蒸汽机的能源效率图”而闻名,此后便以其名字命名为“桑基图”。
前两天正好碰到了这类“数据流量”的可视化问题,因此花了点时间学习了一下桑基图的画法,比较简单,在这里给大家演示一下:
我自己编了一个数据,如下图所示
左边是数据的流向,右边是用表格的形式重写,左图的每一个箭头对应右图的每一行,画桑基图时用到的数据就是右边格式的表格。
下面就是代码
library(networkD3)
library(tidyverse)
library(RColorBrewer)
#读取刚才的数据框,给列命名
df=read.table("test.txt",header = F,sep = " ",stringsAsFactors = F)
colnames(df)=c("source","target","value")
#图形中的所有节点
df.nodes <- data.frame(
name=c(as.character(df$source),
as.character(df$target)) %>% unique()
)
#将source和target重新编号
df$IDsource <- match(df$source, df.nodes$name)-1
df$IDtarget <- match(df$target, df.nodes$name)-1
#这一步是为了给flow自定义颜色,单独定义了一列
df$group="flow"
#配置颜色部分,形式相对固定,不必纠结具体的语法规则
#编码对应的颜色可以用RColorBrewer包结合scales包查看
my_color <- 'd3.scaleOrdinal()
.domain(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J","flow"])
.range(["#8DD3C7", "#FFFFB3", "#BEBADA", "#FB8072", "#80B1D3", "#FDB462", "#B3DE69", "#FCCDE5", "#BC80BD", "#CCEBC5","#BDBDBD"])'
#画图
Sankey.p <- sankeyNetwork(Links = df, Nodes = df.nodes,
Source = "IDsource", Target = "IDtarget",
Value = "value", NodeID = "name", LinkGroup = "group",colourScale=my_color,
sinksRight=FALSE, nodeWidth=25, nodePadding=10, fontSize=13,width=900)
Sankey.p
#画出来的图形,还可以直接在R窗口中调整方块上下位置,不过还是建议保存为pdf后用AI调整
#nodeWidth每个节点方块的宽度
#nodePadding每一列节点方块之间在纵向上的间隔
#width是图形横向的宽度
#保存为pdf
library(htmlwidgets)
saveWidget(Sankey.p, file="Sankey.html")
library(webshot)
webshot("Sankey.html", "Sankey.pdf")
最后的效果是这样的,嗯...还需调整
公众号后台回复20210325,获取今天的代码和测试数据
因水平有限,有错误的地方,欢迎批评指正!