你知道如何使用R语言绘制桑基图吗?
小锐当然知道啦,并且教你
绘制酷炫的桑基图。
开课啦
桑基图(Sankey)是一种特定类型的流程图,图中延伸的分支的宽度对应数据流量的大小,其最明显的特征就是,始末端的分支宽度相等,即所有主支宽度的总和应与所有分出去的分支宽度的总和相等,保持能量的平衡。
今天小锐就介绍一下,如何使用R语言绘制这种酷炫的桑基图。
安装并调用“networkD3”绘图包
install.packages("networkD3")
library(networkD3)
加载数据:
mydata1 <- data.frame(class=c("人文社科","教育","教育","科技","科技","科技","经管"),
type=c("社会科学","教辅类","工具书","计算机","计算机","微生物","金融"),
name=c("社会百科","算法图解","牛津词典","算法图解","python入门","消失的微生物","货币金融学"),
value=c(33,10,13,14,55,26,12),stringsAsFactors=FALSE)
> 查看原始数据:
mydata1
![]() |
3.整理数据,以满足绘图要求:
首先,按能量平衡原则,计算各层级value值,按层级关系以长表格形式列出
mydata2<-aggregate(mydata1[,4],by=list(mydata1$class,mydata1$type),FUN=sum)
mydata1 <- mydata1[,-1]
names(mydata2) <- c("source","target","value")
names(mydata1) <- c("source","target","value")
mydata <- rbind(mydata2,mydata1)
> 查看数据形式:
mydata
![]() |
然后,将mydata数据中的“source”“target”替换成索引值(注:index以0开始)
Sankeylinks <- mydata
Sankeynodes <- data.frame(name=unique(c(Sankeylinks$source,Sankeylinks$target)))
Sankeynodes$index <- 0:(nrow(Sankeynodes) - 1)
Sankeylinks <- merge(Sankeylinks,Sankeynodes,by.x="source",by.y="name") #替换source列
Sankeylinks <- merge(Sankeylinks,Sankeynodes,by.x="target",by.y="name") #替换target列
Sankeydata <- Sankeylinks[,c(4,5,3)] #只保留索引值列,用于绘图
names(Sankeydata) <- c("Source","Target","Value")
Sankeyname <- Sankeynodes[,1,drop=FALSE]
> 查看整理好的绘图数据:
Sankeydata
![]() |
4.经过3.1和3.2的数据整理后,终于要绘制Sankey图:
> 首先了解下绘图参数:
Link:包含每个link的Source、Target和Value值的数据框;
Nodes:包含节点id和节点属性的数据框;
Source:字符串形式,Link数据框中的“Source”变量;
Target:字符串形式,Link数据框中的“Target”变量;
Value:字符串形式,Link数据框中的“Value”变量;
NodeID:字符串形式,指定节点中的节点ID,索引必须以0开始;
fontSize:设置字体大小;
height:桑基图的帧区域的高度(以像素为单位);
width:桑基图的帧区域的宽度(以像素为单位);
nodeWidth:设置节点宽度;
sinksRight:调节最后节点文字标注方向。布尔值,TRUE:标注在左侧,FALSE:标注在右侧。
> 绘制并保存桑基图:
sank <- sankeyNetwork(Links=Sankeydata, Nodes=Sankeyname, Source ="Source", Target = "Target", Value = "Value", NodeID = "name", fontSize = 12, nodeWidth = 30, height = 600, width = 800, sinksRight=FALSE)
saveNetwork(sank, "test.html")
![]() |
了解了桑基图的基本绘图方法后,将范例数据换成你的实际数据,你也可以绘制一张你的专属桑基图,快快行动起来吧!