之所以会想到写关于桑基图的内容是因为最近工作需要,研究了下桑基图,发现网络上和桑基图相关的真实可用的资料少之又少,所以决定出这篇博客,讲讲如何用R语言绘制桑基图。
什么是桑基图?
它是一种特定类型的流程图,图中延伸的分支的宽度对应数据流量的大小,通常应用于能源、材料成分、金融等数据的可视化分析。因1898年Matthew Henry Phineas Riall Sankey绘制的“蒸汽机的能源效率图”而闻名,此后便以其名字命名为“桑基图”。
原本是用在工程学上的图形,但是因为用来表述各个大类别间的区别与联系很直观,所以我拿来描述区域与门店间销售的区别与联系。
怎么画桑基图?
R语言里面主要用networkD3包绘制,核心是sankeynetwork()函数,函数细节
sankeyNetwork(Links, Nodes, Source, Target, Value, NodeID, NodeGroup = NodeID,
LinkGroup = NULL, units = "",
colourScale = JS("d3.scaleOrdinal(d3.schemeCategory20);"), fontSize = 7,
fontFamily = NULL, nodeWidth = 15, nodePadding = 10, margin = NULL,
height = NULL, width = NULL, iterations = 32, sinksRight = TRUE)
首先载入包,读入基础数据,数据集包含5个区域,每个区域中有四种类型的门店,我们要观察每个区域中各个类型门店的销售情况
> library(networkD3)
> sankey<-read.csv("mydata.csv",header=TRUE)
> str(sankey)
'data.frame': 20 obs. of 3 variables:
$ 区域: Factor w/ 5 levels "区域A","区域B",..: 1 1 1 1 2 2 2 2 3 3 ...
$ 门店: Factor w/ 4 levels "门店1","门店2",..: 1 2 3 4 1 2 3 4 1 2 ...
$ 销量: int 100 300 140 20 1640 800 440 190 460 460 ...
接下来准备绘制桑基图,桑基图的数据结构有三列,第一列起点,第二列终点,第三列权重,我们接下来所有的操作都是为了构造出符合要求的数据框:
> network <- sankey[,1:3]#生成一张新表,命名network,取出需要的列数据
> colnames(network) <- c("区域", "门店", "销量")#给新表各列命名
> factor_list <- sort(unique(c(levels(network$区域), levels(network$门店))))#列出起点、终点的列名以及各列具体类别名称
> num_list <- 0:(length(factor_list)-1)#识别出图的节点长度,因为从0开始,所以最终要减1
> levels(network$区域) <- num_list[factor_list %in% levels(network$区域)]#识别各区域节点数
> levels(network$门店) <- num_list[factor_list %in% levels(network$门店)]#识别各门店节点数
> network$区域 <- as.numeric(as.character(network$区域))#因子型数据转为数据型
> network$门店 <- as.numeric(as.character(network$门店))
> attribute <- data.frame(name=c(factor_list))#构造数据框,命名attribute,包含各级因子名称
绘制桑基图,使用sankeynetwork函数,数据集使用network数据集,节点根据factor_list得到,起点是区域,终点是门店,对应值是销量
> sankeyNetwork(Links = network, Nodes = attribute,
+ Source = "区域", Target = "门店",
+ Value = "销量", NodeID = "name", units = "TWh",
+ fontSize= 12, nodeWidth = 30)
最终画出来的图是这样:
观察这幅图,可以看到区域中区域B销量最大,门店中门店1这种类型的门店销量最大,各个类型门店的主要销售都是来自区域B,区域C的主要销售集中在门店1和2,同理区域E,区域A则是最大销售来自门店2,等等,通过仔细观察,可以得到不少信息,桑基图绘制目的就是让各类别间的区别和联系更加直观展现出来。今天的分享到此结束,下次再见!