最近有碰到用python工具包Pyecharts来绘制桑基图Sankey的任务,其实操作起来并不难,但还是会碰到一些问题,在这里我把我的一些实操过程总结一下,中间有些例子会用到别人的博客,我都注明一下出处。
首先来看一个桑基图官方文档给出的例子
桑基图官方文档
official
from pyecharts import options as opts
from pyecharts.charts import Sankey
nodes = [
{“name”: “category1”},
{“name”: “category2”},
{“name”: “category3”},
{“name”: “category4”},
{“name”: “category5”},
{“name”: “category6”},
]
links = [
{“source”: “category1”, “target”: “category2”, “value”: 10},
{“source”: “category2”, “target”: “category3”, “value”: 15},
{“source”: “category3”, “target”: “category4”, “value”: 20},
{“source”: “category5”, “target”: “category6”, “value”: 25},
]
c = (
Sankey()
.add(
“sankey”,
nodes,
links,
linestyle_opt=opts.LineStyleOpts(opacity=0.2, curve=0.5, color=“source”),
label_opts=opts.LabelOpts(position=“right”),
)
.set_global_opts(title_opts=opts.TitleOpts(title=“Sankey-基本示例”))
.render(“sankey_base.html”)
)
大概绘制出来就是
桑基图其实比较关键的两个点就是nodes和links,也就是节点和流向。节点说白了就是对象,发出对象和接收对象都是节点,流向其实就是具体的方向和值(value),当然它的表示的方式就是给出首尾点,也就是source和target。所以桑吉图就是把从source到target的value给画出来,它完成的就是图像化links的任务。
在这里需要注意几个点:
1.nodes中的"name"不要重新命名,否则会不识别,导致没有图
2.links中source和target对应的值一定要在nodes的name对应的值中,否则图中会不显示(但是不会报错),也就是存在的节点一定要被name定义一下
3.links中source和target对应的值不能相同,否则图不显示
其中3说的并不是单一流向中的source和target不能相同,而是所有的都不能相同,举个例子,比如你要表示A到B“流入”X的值,然后B到A再“流出”Y的值,在理解意义里面,A和A是一个东西,但是桑基图里面得分开name,比如A1到B,B到A2,A1和A2在现实意义中当然是同一个个体(自己开始没弄清楚,做一个银行户口的流入流出,一个A银行资金流入B,B又流回A,这两个A得想办法区分开,做了source的name不能再做target了。
其次,来看看实操过程
实操的话一般有两种,第一种比较简单了,就是在代码里面直接把nodes和links写清楚,就像上面的官方文档一样,画图就可以了,另外就在下面的linestyle里面设置一下具体的图画格式,这个后面会讲,第二种就是我觉得比较常用的了,就是把excel表里的内容导出来,然后画桑基图,在这里讲一下第二种。
import pandas as pd
from pyecharts.charts import Sankey
from pyecharts import options as opts
df = pd.read_excel(‘文件路径’, header = 0) #打开文件路径
在这里用一个别人的例子哈,来源【手把手教你用 Python 绘制酷炫的桑基图】()
nodes = []
for i in range(2): #历遍df中前两列不重复的项
values = df.iloc[:, i].unique() #iloc: 根据标签所在位置,从0开始计数,i列所有行; eg. iloc[0]= 第一行;iloc[0,0]=第一行第一列的项
#创建一个dictionary:{name:***}
for value in values:
dic = {}
dic[‘name’] = value
nodes.append(dic)
在df的值里面,第一列作为source,第二列作为target,第三列作为value,画出流向图
然后是固定格式绘制代码
from pyecharts.charts import Sankey
from pyecharts import options as opts
pic = (
Sankey()
.add(‘’, #图例名称
nodes, #传入节点数据
linkes, #传入边和流量数据
#设置透明度、弯曲度、颜色
linestyle_opt=opts.LineStyleOpts(opacity = 0.3, curve = 0.5, color = “source”),
#标签显示位置
label_opts=opts.LabelOpts(position=“right”),
#节点之前的距离
node_gap = 30,
)
.set_global_opts(title_opts=opts.TitleOpts(title = ‘熬夜原因桑基图’))
)
pic.render(‘test.html’)
这个是两层,如果涉及到多层的表示,在数据处理上要做一下文章
而linkes只接受source-traget-value的格式,得先对源数据进行格式调整,分别形成“品类-第一次购买-人数”,“第一次购买-第二次购买-人数”的样式,再统一汇总:
secnotallow= df.iloc [:,1:] 这里的意思是从第二列开始后面所有的列中所有行的值,
当然也可以写成
second = df.grouphy(['第一次购买’,‘第二次购买’])['人数‘].sum().reset_index()
关于iloc的用法,可以看python中iloc函数
#first = df.iloc[: ] #.rest_index() ##汇总相应数据
#second = df.iloc[: ] ##从汇总中提取相应数据
#first.column = [‘source’, ‘target’, ‘value’]
#second.column = [‘source’, ‘target’, ‘value’]
#result = pd.concat([first, second]) ##将first,second合并
#result.head(10)
#result
#first = df.[]
#first
#linkes = []
#创建一个dictionary:{‘source’: **, ‘target’: **, ‘target’: **}
for i in df.values:
dic = {}
dic[‘source’] = i[0]
dic[‘target’] = i[1]
dic[‘value’] = i[2]
linkes.append(dic)
linkes
规整汇总好之后,只需要复用上面的linkes代码:
pic = (
Sankey()
.add(‘’,
nodes,
linkes,
linestyle_opt=opts.LineStyleOpts(opacity = 0.3, curve = 0.5, color = ‘source’),
label_opts=opts.LabelOpts(position = ‘top’),
node_gap = 30,
)
.set_global_opts(title_opts=opts.TitleOpts(title = ‘客户购买路径流转图’))
)
pic.render(‘test3.html’)
当然这个图是横着放还是竖着放,就是top和right的关系了
再就是关于这些图的一些参数调整
1 .信息流的格式配置(颜色、透明度、曲线程度)
add()里面,使用参数 linestyle_opt进行配置
配置格式为linestyle_opt=opts.LineStyleOpts(参数)。参数的配置参考
A Python Echarts Plotting Library
以下设置颜色为节点颜色,透明度,曲线弯曲度。
color="source"表示使用节点的颜色。
,linestyle_opt=opts.LineStyleOpts(opacity=0.2 ###透明度设置
, curve=0.5 ###信息流的曲线弯曲度设置
,color=“source” ##颜色设置,source表示使用节点的颜色
) ##线条格式 ,设置所有线条的格式
)
)
2 .标签的格式配置(大小、颜色、位置)
修改信息流的格式之后,标签的显示并不明显,接下来修改一下标签的格式。
方式为:add()里面,使用参数 label_opts进行配置
配置格式为label_opts=opts.LabelOpts(参数)。
,linestyle_opt=opts.LineStyleOpts(opacity=0.2 ###透明度设置
, curve=0.5 ###信息流的曲线弯曲度设置
,color=“source” ##颜色设置,source表示使用节点的颜色
) ##线条格式 ,设置所有线条的格式
,label_opts=opts.LabelOpts(font_size=16
,position=‘left’
) ##标签配置,具体参数详见opts.LabelOpts()
)
)
3 . 配置每一层节点的颜色
有时候需要将同一层节点的颜色配置为一致的,我们可以通过level参数逐层配置节点和信息流的格式。
配置格式为:
levels= [opts.SankeyLevelsOpts(参数) ###某一层节点和信息流的配置
,opts.SankeyLevelsOpts(参数) ###某一层节点和信息流的配置
,opts.SankeyLevelsOpts(参数) ###某一层节点和信息流的配置
]
,linestyle_opt=opts.LineStyleOpts(opacity=0.2 ###透明度设置
, curve=0.5 ###信息流的曲线弯曲度设置
,color=“source” ##颜色设置,source表示使用节点的颜色
) ##线条格式 ,设置所有线条的格式
,label_opts=opts.LabelOpts(font_size=16
,position=‘left’
) ##标签配置,具体参数详见opts.LabelOpts()
,levels= [opts.SankeyLevelsOpts( depth=0, ##第一层的配置
itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),##节点格式的配置
linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))##信息流的配置
,opts.SankeyLevelsOpts( depth=1,##第二层的配置
itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),##节点格式的配置
linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))##信息的配置
,opts.SankeyLevelsOpts( depth=2,##第三层的配置
itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"),##节点格式的配置
linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))##信息的配置
]# 桑基图每一层的设置。可以逐层设置
)
)
4 . 对齐方式的配置
如果个别节点没有下级节点,其他的节点有下级节点,为了美观一些,可以选择的节点对齐的方式。通过node_align参数进行配置。
,node_align=‘left’ # 桑基图中节点的对齐方式,默认是双端对齐,可以设置为左对齐或右对齐,对应的值分别是:
# justify: 节点双端对齐。
# left: 节点左对齐。
# right: 节点右对齐
,linestyle_opt=opts.LineStyleOpts(opacity=0.2 ###透明度设置
, curve=0.5 ###信息流的曲线弯曲度设置
,color=“source” ##颜色设置,source表示使用节点的颜色
) ##线条格式 ,设置所有线条的格式
,label_opts=opts.LabelOpts(font_size=16
,position=‘left’
) ##标签配置,具体参数详见opts.LabelOpts()
,levels= [opts.SankeyLevelsOpts( depth=0, ##第一层的配置
itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),##节点格式的配置
linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))##信息流的配置
,opts.SankeyLevelsOpts( depth=1,##第二层的配置
itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),##节点格式的配置
linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))##信息的配置
]# 桑基图每一层的设置。可以逐层设置
)
)
以上有内容借鉴pyecharts 学习篇☞桑基图实用示例,侵删
最后说一个小问题
如果出现了标题却没有桑基图,可以检查一下浏览器的设置是不是安全性组织了弹出,不过这个可能性比较小,另外就是主要用于无法访问html中的"https://assets.pyecharts.org/assets/echarts.min.js",可在无法联网时使用
方法为:手动定制下载echarts.min.js,复制到本地,然后修改.html文件 “https://assets.pyecharts.org/assets/echarts.min.js"为相对路径”./echarts.min.js"
详细可看Pyecharts 1.7.0制作图表,运行生成的html文件用浏览器打开空白问题(以桑基图为例)