日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

炫酷!用Python制作漂亮的流动桑基图

發布時間:2024/9/15 python 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 炫酷!用Python制作漂亮的流动桑基图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:Peter

整理:Lemon

桑基圖繪制實踐

本文中介紹的是如何制作桑基圖,使用的可視化庫是強大的 Pyecharts (版本1.7.1,版本一致很重要)。文章將從如下幾個方面進行介紹:

  • 什么是桑基圖

  • 官網的兩個 demo

  • 桑基圖繪制項目實戰

在開始之前,我們先來看看通過本文制作的最終效果圖:

什么是桑基圖?

桑基圖(桑葚圖),也叫桑基能量分流圖或者桑基能量平衡圖,里面的桑基其實是一個人名,全名是 馬修·亨利·菲尼亞斯·里爾·桑基(Matthew Henry Phineas Riall Sankey) ,是一名愛爾蘭裔工程師,也是英國皇家陸軍工兵的上尉[1]

早在 1898 年的時候,他就使用這種圖形來表示蒸汽機的能源效率:

桑基之后,桑基圖逐漸成為科學和工程領域,代表平衡、能量流、物質流的標準模型,在一些產品的生命周期評估中也常被使用,通常應用于能源、材料成分、金融等數據的可視化分析。主要特點是:

  • 圖形由邊、流量和支點組成。邊代表了流動的數據,流量代表了流動數據的具體數值,節點代表了不同分類

  • 始末端的分支寬度總和相等,即所有主支寬度的總和應與所有分出去的分支寬度的總和相等,保持能量的平衡。

官網demo

本文中使用的Pyecharts版本是1.7.1,版本的一致非常重要。

import?pyecharts pyecharts.__version__

demo_1

首先我們看看官網的第一個demo:

from?pyecharts?import?options?as?opts from?pyecharts.charts?import?Sankeynodes?=?[???#?所有節點名稱{"name":?"category1"},{"name":?"category2"},{"name":?"category3"},{"name":?"category4"},{"name":?"category5"},{"name":?"category6"}, ]links?=?[??#?每一條鏈路的數據,包含:父節點source +?子節點target +?數據值value{"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")????生成HTML文件 )c.render_notebook()???#?jupyter?notebook中在線顯示

在上面的代碼中,nodes部分表示的是所有的節點名稱,不管是父節點還是最小的子節點都要列出來;links部分表示的是每條鏈路的數據,包含:父節點source + 子節點target + 數據值value。根據links的數據,我們可以發現:category1——-category2———category3———category4構成了一條完整的鏈路,category5—category6構成了另一條鏈路。

下面是最終的圖形:

demo_2

接下來我們看看官網的第二個demo:

import?jsonfrom?pyecharts?import?options?as?opts from?pyecharts.charts?import?Sankeywith?open("product.json",?"r",?encoding="utf-8")?as?f:???#?導入json數據j?=?json.load(f)????#?json數據轉成字典數據 c?=?(Sankey().add("sankey",nodes=j["nodes"],???#?取出json數據的節點和鏈路數據links=j["links"],pos_top="10%",focus_node_adjacency=True,levels=[opts.SankeyLevelsOpts(depth=0,itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),opts.SankeyLevelsOpts(depth=1,itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),opts.SankeyLevelsOpts(depth=2,itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"),linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),opts.SankeyLevelsOpts(depth=3,itemstyle_opts=opts.ItemStyleOpts(color="#decbe4"),linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),],linestyle_opt=opts.LineStyleOpts(curve=0.5),).set_global_opts(title_opts=opts.TitleOpts(title="Sankey-Level?Settings"),tooltip_opts=opts.TooltipOpts(trigger="item",?trigger_on="mousemove"),) #????.render("sankey_with_level_setting.html") )c.render_notebook()???#?在線顯示
  • 讀取本地的json數據,通過josn.load()讀取轉成Python字典

  • 取出json數據中的節點和鏈路數據進行繪圖

桑基圖繪制實踐

原始數據整理

通過上面官網的例子我們明白了繪制桑基圖需要的兩個數據:節點數據+鏈路數據,下面????通過一個實際的案例來講解如何生成繪制桑基圖需要的數據

認識原始數據

Peter同學一個人在深圳搬磚,辛辛苦苦地搬了一個月,產生很多的開銷????,這些開支主要分成5大塊:

  • 住宿

  • 餐飲

  • 交通

  • 服裝

  • 紅包

每個部分又分別有不同的去向,所以這些數據就自然構成了一條條的鏈路,比如:總費用—住宿—房租(2000),總費用—交通—滴滴(220)等,我們只考慮兩個節點之間的關系

分層級整理數據

1、接下來我們分不同的層級來整理原始數據,首先是第一層:總費用到5個子版塊。算出每個子版塊的總和

2、整理5個子版塊的數據

3、我們將上面兩個步驟得到的數據放入一個sheet中,命名為開支:

桑基圖數據生成

讀取數據

首先我們將上面制作好的開支這份數據讀到pandas中:

import?pandas?as?pd import?numpy?as?np import?json#?等價于:data = pd.read_excel("life.xlsx",sheet_name=1)? 1表示sheet_name的索引位置,索引從0開始 df?=?pd.read_excel("life.xlsx",sheet_name="開支")??#?直接寫名字 df.head()

注意兩點:

  • 當一個表格中存在多個sheet的時候,我們需要指定sheet_name的名字

  • 指定sheet_name的名字有兩種方式:

  • 直接指定名字

  • 指定該sheet_name的位置索引

  • 確定全部節點nodes

    1、先找出全部的節點

    所有的節點數據就是上面的父類和子類中去重后的元素,我們使用集合set進行去重,再轉成列表

    #?父類+子類中的數據,需要去重df['父類'].tolist() df['子類'].tolist()

    將上面的數據相加并且去重:

    #?將兩個列表相加,在轉成集合set進行元素去重,再轉成列表nodes?=?list(set(df['父類'].tolist()?+?df['子類'].tolist()))? nodes

    2、生成節點數據

    #?節點列表數據:?nodes_listnodes_list?=?[] for?i?in?nodes:dic?=?{}dic["name"]?=?inodes_list.append(dic) nodes_list

    生成鏈路數據

    我們將導入的數據生成鏈路數據:每一行記錄都是一個鏈路數據:

    links_list?=?[]for?i?in?range(len(df)):dic?=?{}dic['source']?=?df.iloc[i,0]??#?父類dic['target']?=?df.iloc[i,1]??#?子類dic['value']?=?int(df.iloc[i,2])???#?數據值?:?使用int函數直接強制轉換,防止json.dump()報錯links_list.append(dic)

    Attention??:導入的數據部分需要強制轉換成int類型,防止后面的數據處理報錯。

    到此為止,我們已經完成了桑葚圖中節點數據和鏈路數據的生成,下面開始繪圖。

    繪制桑基圖

    我們通過官網的2種不同方式來繪制桑基圖

    方式1

    這種方式比較簡單:直接將上面得到的nodes_list和links_list整體放入繪圖的代碼中:

    #?需要事先導入,否則jupyter?notebook中可能不會出圖 from?pyecharts.globals?import?CurrentConfig,?OnlineHostType from?pyecharts?import?options?as?opts??#?圖形設置 from?pyecharts.charts?import?Sankey????#?導入桑基圖型的類nodes_list?=?[{'name':?'圍巾'},{'name':?'長輩'},{'name':?'網絡費'},{'name':?'服裝'},{'name':?'公交'},{'name':?'同學'},{'name':?'襪子'},{'name':?'總費用'},{'name':?'衣服'},{'name':?'紅包'},{'name':?'交通'},{'name':?'聚餐'},{'name':?'滴滴'},{'name':?'餐飲'},{'name':?'管理費'},{'name':?'水電'},{'name':?'共享單車'},{'name':?'外賣'},{'name':?'房租'},{'name':?'住宿'},{'name':?'飲料'},{'name':?'鞋子'},{'name':?'地鐵'} ]links_list?=?[{'source':?'總費用',?'target':?'住宿',?'value':?2580},{'source':?'總費用',?'target':?'餐飲',?'value':?1300},{'source':?'總費用',?'target':?'交通',?'value':?500},{'source':?'總費用',?'target':?'服裝',?'value':?900},{'source':?'總費用',?'target':?'紅包',?'value':?1300},{'source':?'住宿',?'target':?'房租',?'value':?2000},{'source':?'住宿',?'target':?'水電',?'value':?400},{'source':?'住宿',?'target':?'管理費',?'value':?100},{'source':?'住宿',?'target':?'網絡費',?'value':?80},{'source':?'餐飲',?'target':?'外賣',?'value':?800},{'source':?'餐飲',?'target':?'聚餐',?'value':?300},{'source':?'餐飲',?'target':?'飲料',?'value':?200},{'source':?'交通',?'target':?'滴滴',?'value':?220},{'source':?'交通',?'target':?'地鐵',?'value':?150},{'source':?'交通',?'target':?'公交',?'value':?80},{'source':?'交通',?'target':?'共享單車',?'value':?50},{'source':?'服裝',?'target':?'衣服',?'value':?400},{'source':?'服裝',?'target':?'鞋子',?'value':?300},{'source':?'服裝',?'target':?'圍巾',?'value':?150},{'source':?'服裝',?'target':?'襪子',?'value':?50},{'source':?'紅包',?'target':?'同學',?'value':?800},{'source':?'紅包',?'target':?'長輩',?'value':?500} ]c?=?(Sankey().add("月度開支",nodes_list,links_list,linestyle_opt=opts.LineStyleOpts(opacity=0.5,?curve=0.5,?color="source"),label_opts=opts.LabelOpts(position="right"),).set_global_opts(title_opts=opts.TitleOpts(title="月度開支桑葚圖")) )c.render_notebook()

    得到的桑基圖在notebook中是動態的圖形:

    動態視頻效果如下:

    方式2

    如果數據比較少,將nodes_list和links_list放入繪圖的代碼中不會占據過多的空間;但是如果數據量大,不同鏈路種類多,全部放在整個繪圖代碼中,就會顯得整個代碼很臃腫。

    于是產生了方式2:先將上面得到的nodes_list和links_list生成一個json文件,再將json文件通過with方法讀進來進行繪圖。下面講解如何通過得到的nodes_list和links_list數據生成我們繪圖需要的json數據。

    json格式的數據,在python中以字符串的形式呈現,一定要用雙引號括起來。json模塊中提供的4個功能:

    • dumps:python字典數據類型轉成json數據類型的字符串

    • dump:字典數據轉成字符串并且存儲在文件中

    • loads:把json字符串轉成字典數據類型

    • load:把文件打開,并且從字符串轉換成字典數據類型

    1、先生成字典數據

    data_dic?=?{}data_dic["nodes"]?=?nodes_list data_dic["links"]?=?links_list

    得到的字典data_dic數據分為節點數據和鏈路數據,具體如下:

    {'nodes':?[{'name':?'圍巾'},???#?節點部分數據{'name':?'長輩'},{'name':?'網絡費'},{'name':?'服裝'},{'name':?'公交'},{'name':?'同學'},{'name':?'襪子'},{'name':?'總費用'},{'name':?'衣服'},{'name':?'紅包'},{'name':?'交通'},{'name':?'聚餐'},{'name':?'滴滴'},{'name':?'餐飲'},{'name':?'管理費'},{'name':?'水電'},{'name':?'共享單車'},{'name':?'外賣'},{'name':?'房租'},{'name':?'住宿'},{'name':?'飲料'},{'name':?'鞋子'},{'name':?'地鐵'}],'links':?[{'source':?'總費用',?'target':?'住宿',?'value':?2580},??#?鏈路部分數據{'source':?'總費用',?'target':?'餐飲',?'value':?1300},{'source':?'總費用',?'target':?'交通',?'value':?500},{'source':?'總費用',?'target':?'服裝',?'value':?900},{'source':?'總費用',?'target':?'紅包',?'value':?1300},{'source':?'住宿',?'target':?'房租',?'value':?2000},{'source':?'住宿',?'target':?'水電',?'value':?400},{'source':?'住宿',?'target':?'管理費',?'value':?100},{'source':?'住宿',?'target':?'網絡費',?'value':?80},{'source':?'餐飲',?'target':?'外賣',?'value':?800},{'source':?'餐飲',?'target':?'聚餐',?'value':?300},{'source':?'餐飲',?'target':?'飲料',?'value':?200},{'source':?'交通',?'target':?'滴滴',?'value':?220},{'source':?'交通',?'target':?'地鐵',?'value':?150},{'source':?'交通',?'target':?'公交',?'value':?80},{'source':?'交通',?'target':?'共享單車',?'value':?50},{'source':?'服裝',?'target':?'衣服',?'value':?400},{'source':?'服裝',?'target':?'鞋子',?'value':?300},{'source':?'服裝',?'target':?'圍巾',?'value':?150},{'source':?'服裝',?'target':?'襪子',?'value':?50},{'source':?'紅包',?'target':?'同學',?'value':?800},{'source':?'紅包',?'target':?'長輩',?'value':?500}]}

    2、將生成的字典數據轉成json數據,并保存到本地

    通過json.dump方法將上面生成的字典類型數據轉成json數據,并保存到本地:

    with?open("sankey.json","w",encoding="utf-8")?as?f:???#?數據保存到了本地#?json.dump(data_dic,?f)???寫入一行數據json.dump(data_dic,?f,?indent=2,?sort_keys=True,?ensure_ascii=False)??#?寫入多行數據

    3、讀取json數據進行繪圖

    import?jsonfrom?pyecharts?import?options?as?opts from?pyecharts.charts?import?Sankeywith?open("sankey.json",?"r",?encoding="utf-8")?as?f:???#?1、打開保存的文件j?=?json.load(f)???#?2、json字符串轉成字典類型數據 c?=?(Sankey().add("月度開支",nodes=j["nodes"],???#?3、通過鍵值對的映射關系來讀取數據links=j["links"],pos_top="20%",focus_node_adjacency=True,levels=[opts.SankeyLevelsOpts(depth=0, #?????????????????itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),??4、屬性的設置部分linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),opts.SankeyLevelsOpts(depth=1, #?????????????????itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),opts.SankeyLevelsOpts(depth=2, #?????????????????itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"),linestyle_opts=opts.LineStyleOpts(color="source",?opacity=0.6),),],linestyle_opt=opts.LineStyleOpts(curve=0.5,color="source",opacity=0.6,type_="dotted"),label_opts=opts.LabelOpts(position="right")).set_global_opts(title_opts=opts.TitleOpts(title="月度開支桑葚圖"),tooltip_opts=opts.TooltipOpts(trigger="item",?trigger_on="mousemove|click",is_show=True),) )c.render_notebook()

    看看實際的動態化效果:

    參考資料

    [1]

    桑基的介紹: https://zhuanlan.zhihu.com/p/127360262

    作者簡介

    Peter,碩士畢業僧一枚,從電子專業自學Python入門數據行業,擅長數據分析及可視化。喜歡數據,堅持跑步,熱愛閱讀,樂觀生活。個人格言:不浮于世,不負于己

    個人站點:www.renpeter.cn,歡迎常來小屋逛逛


    往期推薦: 收藏 | 49 個 Python 學習資源我都逛哪些技術網站?(程序員必備58個網站匯總)肝!精心整理了 50 個數據源網站!

    總結

    以上是生活随笔為你收集整理的炫酷!用Python制作漂亮的流动桑基图的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 成人免费一级视频 | 国产又粗又猛又大爽 | 超碰免费97 | 成人福利在线 | 久久久久久久久免费看无码 | 男男做爰猛烈啪啪高 | 国产成人精品一区 | 亚洲色图视频网站 | 中文字幕女同女同女同 | 免费看污黄网站在线观看 | 强行糟蹋人妻hd中文字幕 | 大香蕉视频一区二区 | av中文字幕网站 | 91老师国产黑色丝袜在线 | 欧美成人手机在线视频 | 国产精品日韩一区二区 | 椎名空在线观看 | 一个人在线观看www www.97色 | 免费视频一二三区 | 中文字幕5566| 免费av资源 | 草久网| 亚洲欧美激情视频 | 日韩免费观看一区二区三区 | 永久av免费在线观看 | 呦呦网| 山村大伦淫第1部分阅读小说 | 粉嫩精品久久99综合一区 | 色哟哟一区二区三区四区 | 亚洲色成人网站www永久四虎 | 狼人综合网 | 九九热视频精品在线观看 | 夜夜嗨av一区二区三区四区 | 国产色黄 | 国产精品麻豆一区二区 | 亚洲性喷水 | 91亚洲精品一区二区乱码 | gv天堂gv无码男同在线观看 | 精品欧美视频 | 国产精品3 | 福利一二区 | 日本高清无吗 | 亚洲综合色吧 | av在线不卡一区 | 99热这里只有精品在线观看 | 人妖粗暴刺激videos呻吟 | 四虎永久在线精品免费网址 | 亚洲字幕成人中文在线观看 | 国产乱子伦精品无码码专区 | jizz亚洲女人高潮大叫 | 377p粉嫩大胆色噜噜噜 | 日韩性xxxx| 先锋影音av中文字幕 | 国产女主播自拍 | 鲁一鲁在线视频 | 无码国产精品一区二区免费式直播 | 日本伦理一区二区 | 宇都宫紫苑在线播放 | 可以看av的网站 | 日日夜夜操操操 | 午夜一区二区三区免费观看 | 成人免费黄色网 | 天天操天天操天天操 | 免费在线观看黄网站 | 亚洲精品色午夜无码专区日韩 | 熟妇大屁股一区二区三区视频 | 国产精品刘玥久久一区 | 大片视频免费观看视频 | 国产成人综合欧美精品久久 | 久久精品国产精品亚洲毛片 | 激情小说图片视频 | 在线观看av不卡 | 日本亚洲色图 | 国产精品久久久久久久 | 好吊视频一区二区 | 激情婷| 少妇高潮一区二区三区69 | 免费在线观看网址入口 | 亚洲精品白浆高清久久久久久 | 神马午夜电影一区二区三区在线观看 | 色操插| 亚洲第一视频在线 | 超碰2025| 天天高潮夜夜爽 | 国产精品久久婷婷 | 国产a级免费 | 国产96视频 | 一本久久精品一区二区 | av不卡一区二区 | 97国产精品久久 | 日韩黄色片免费看 | 一区二区三区日韩电影 | 国产xxx69麻豆国语对白 | 久久久黄色| 欧美成年人视频 | 91成人观看| 在线观看国产视频 | 日日爱av | 91性色|