前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pyecharts实现多节点、长路径的sankey桑基图

pyecharts实现多节点、长路径的sankey桑基图

作者头像
悟乙己
发布2021-12-07 15:50:44
7720
发布2021-12-07 15:50:44
举报
文章被收录于专栏:素质云笔记素质云笔记

1 画桑基图一个容易出错的细节

pyecharts︱交互式pyecharts的相关使用教程

简单的用pyecharts实现超多节点、较长路径的桑基图,一个样图:

起先拿网络教程里的数据跑的时候没有任何问题,然后用自己的数据,就一直显示空白,

内有内容显示,找了很久问题,发现了一个很多网上教程都没有说的点,

需要用pyecharts划超多节点的话,一定需要留意:

举例来说,这个简单的桑基图,如果你的数据里面出现了category6 -> category2这种逆流向的,大概率会显示空白,所以这里可以自行约束一下每一列的列名,让其保持独立。

2 代码案例

主要代码:

代码语言:javascript
复制
import pandas as pd
import asyncio

import pyecharts.options as opts
from pyecharts.charts import Sankey
from collections import Counter


'''
数据处理核心环节

每列保留节点数:
    每一列最多保留5个节点,其他都是other,同时按照列进行编码

冲突的节点改名

'''

# reserved_num = 10

def sankey_data_preprocessing(sankey_data_2,reserved_num):

    # 1 定位哪些节点需要变成other 以及 改名
    other_cols_dict = {}
    
    pred_cols = set()
    alter_col_dict = {}
    for col in sankey_data_2.columns :
        # 每列保留节点数:
        other_cols_dict[col] = list(sankey_data_2[col].value_counts().index[reserved_num:])
        # 冲突节点处理
        alter_col_dict[col] = {}
        if col != 0:
            for pc in set(sankey_data_2[col]):
                if (pc in pred_cols)&(pc != None):
                    alter_col_dict[col][pc]=f'{pc}_{col}'
            
        [pred_cols.add(pc) for pc in set(sankey_data_2[col]) if pc != None]
    
    # 2 修改源数据
    for col in sankey_data_2.columns :
        # 变成other
        sankey_data_2[col] = sankey_data_2[col].map(lambda x :  f'other_{col}'  if x in   other_cols_dict[col] else x    if  x == x else np.nan )
        # 改名
        if col in alter_col_dict.keys():
            sankey_data_2[col] = sankey_data_2[col].map(lambda x :  alter_col_dict[col][x]  if x in   alter_col_dict[col].keys() else x    if  x == x else np.nan )
    
    return sankey_data_2

# 3 生成最终sankey格式
def sankey_standard_format_generator(sankey_data_2):
    num = sankey_data_2.shape[1]
    num_l = list(zip(list(range(num-2)),list(range(2,num))))
    
    result = {}
    
    for part in num_l:
        text_list = sankey_data_2.iloc[:,part[0]:part[1]].apply(lambda x: list(x) ,axis = 1 )  
        text_list = [str(tl) for tl in text_list  if len(tl) == 2  ]  
        print('正在生成区间:',part)    
        #out.extend([eval(k)+[v]  for k,v in Counter(text_list).items()])
        result[part] = [eval(k)+[v]  for k,v in Counter(text_list).items()]
    
    result = [ p  for part in num_l for p in result[part] if p[1] != None    ]
    
    sankey_standard_format = pd.DataFrame(result,columns = ['source','target','value'])
    
    sankey_standard_format = sankey_standard_format[sankey_standard_format['source'] == sankey_standard_format['source']]
    sankey_standard_format = sankey_standard_format[sankey_standard_format['target'] == sankey_standard_format['target']]
    
    
    links = list(sankey_standard_format.T.to_dict().values())
    nodes = list(sankey_standard_format['source'].value_counts().index) + \
        list(sankey_standard_format['target'].value_counts().index)
    nodes = [{'name':l}  for l in list(set(nodes))]
    return links,nodes

data_list = [['模板消息', 'order-list', 'order-detail', 'order-list'],
 ['菜单', 'activity'],
 ['支付卡券', 'product-detail', 'checkout', 'product-detail'],
 ['支付卡券', 'home'], 
 ['搜索',  'home',  'user',  'webview',  'user',  'ugc-list',  'shopping-cart',  'home'],
 ['我的小程序', 'home', 'user', 'order-list', 'order-detail'],
 ['搜索', 'home', 'shopping-cart', 'home'],
 ['模板消息', 'order-list', 'order-detail'],
 ['我的小程序', 'product-detail'],
 ['菜单',  'home',  'star',  'product-list',  'product-detail',  'pgc-detail',  'product-detail',  'product-list']]

sankey_data_2 = pd.DataFrame(data_list)

# 数据预处理
sankey_data_2 = sankey_data_preprocessing(sankey_data_2,10)

# 生成标准的sankey格式
links,nodes = sankey_standard_format_generator(sankey_data_2)
sankey = {"nodes":nodes,"links":links}


(
    Sankey(init_opts=opts.InitOpts(width="3200px", height="1600px"))  # 图像大小
    .add(
        series_name="",
        nodes=sankey["nodes"],
        links=sankey["links"],
        itemstyle_opts=opts.ItemStyleOpts(border_width=0.1, border_color="#1b6199"),
        linestyle_opt=opts.LineStyleOpts(color="source", ##颜色设置,source表示使用节点的颜色
                                         curve=0.5, ###信息流的曲线弯曲度设置
                                         opacity=0.5),##颜色设置,source表示使用节点的颜色
        tooltip_opts=opts.TooltipOpts(trigger_on="mousemove"),
        
        node_align='left'   # 桑基图中节点的对齐方式,默认是双端对齐,可以设置为左对齐或右对齐,对应的值分别是:
                        # justify: 节点双端对齐。
                        # left: 节点左对齐。
                        # right: 节点右对齐
        #,orient='vertical'  # 桑基图中节点的布局方向,可以是水平的从左往右,也可以是垂直的从上往下。
                                # 对应的参数值分别是 horizontal, vertical。
        ,is_selected=True #图例是否选中             
        ,pos_left='20%'##图距离容器左边的距离             
        ,pos_top='20%'##图距离容器上端的距离             
        ,pos_right='20%' #图距离容器右侧的距离             
        ,pos_bottom='20%' ###图距离容器下端的距离             
        #,node_width=10 #桑基图中每个矩形节点的宽度            
        ,node_gap=20 #每一列两个桑基图之间的距离
        ,is_draggable=True ##是否能够拖动节点,默认拖动,可以不配置

        
    )
    .set_global_opts(title_opts=opts.TitleOpts(title="Sankey Diagram"))
    .render("sample.html")
)

其中,

sankey_data_preprocessing预处理很重要,如果某一列节点太多,可以约束一下,其他数量少的,变成other;另外之前提到的逆向指向的问题,也需要修改列名

sankey_standard_format_generator,变成sankey指定需要的标准格式

最后还有非常多可调节的参数,可以参考以下文献:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-06-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 画桑基图一个容易出错的细节
  • 2 代码案例
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档