Python绘制节点是饼状图的社交网络图(Plot network with pie chart)
目錄
問題描述
問題拆解
數據準備
繪圖思路
代碼實現
總結
成圖
network 性質?
參考
問題描述
????????專業描述:想要繪制一幅社交網絡圖,并且每個節點上繪制一個餅狀圖。
???????大白話:韓韓(樓主)有一天突發奇想,想要畫一張圖,可以一目了然的展現好友關系以及不同好友的各項興趣愛好。
問題拆解
數據準備
原始CSV數據下載鏈接:
鏈接:https://pan.baidu.com/s/1LuNH-6YDsoyGqqJL2JbKYA?
提取碼:7as7?
?
好友名單以及興趣愛好表(表名為:friend_node.csv)。
這里的source就是代表樓主和樓主的朋友們,node_label表示樓主及朋友們的名稱。node_size表示樓主和朋友們的相對身高或者balabalaa,任意代表個人屬性的性質。share1-shre4表示樓主及朋友們在攝影、游泳、做飯、瑜伽這四項興趣愛好的相對時間分布情況,這四項相加為100。
樓主與好友的關系表。(表名為:friend_edge.csv)
這里的source和target分別表示樓主和朋友們,比如(1,2)就表示樓主和LL是好朋友。
繪圖思路
用Gephi其實可以做出漂亮的network圖,但是樓主還需要在每個node上添加代表不同朋友的興趣的屬性,Gephi暫時還實現不了。就轉戰python。
繪制思路其實分為如下幾步:
- 提取數據,用python從CSV文件中提取node和edge的數據。現實分析問題時,大都需要處理大量的數據,所以樓主附上此步的code,對python小白來說非常友好。(此處需點贊!!!)
- 選取繪制網絡圖的package,python中有多個package均可實現繪制網絡圖,如NetworkX、PyVis、Visdcc in Dash。(詳細請閱讀:https://towardsdatascience.com/visualizing-networks-in-python-d70f4cbeb259)。樓主選取的是networkX包,(這可能就是第一眼就喜歡上的package,呸,瞎說,第一眼搜到的package)。這個包可以整體繪制網絡圖、也可以將node,edge分次繪制。就類似ps的圖層概念,一層一層畫,疊加起來,順著這個思路,要實現目的,就可以先繪制出edge,然后在每個node的位置繪制上pie圖。之后再補充細節,如添加node的label等。
代碼實現
# -*- coding: utf-8 -*- """ Created on Sun Jun 20 23:21:27 2021@author: HJ """ ############################################################################## import csv import numpy as np import networkx as nx import matplotlib.pyplot as plt############################################################################## ################################# 數據提取 #################################### ############################################################################## ######讀取node的表頭 with open('friend_node.csv', 'r', encoding='UTF-8') as nodecsv: # Open the filereader=csv.reader(nodecsv)header_row=next(reader) for index,column_header in enumerate(header_row):print(index,column_header)######提取node表 with open('friend_node.csv', 'r', encoding='UTF-8') as nodecsv: # Open the filenodereader = csv.reader(nodecsv) # Read the csv 不讀表頭nodes = [n for n in nodereader][1:] print(nodes) node_names = [n[0] for n in nodes]###定義node的weight node_weight = [n[2] for n in nodes]#由于這樣定義的node weigt是文本格式,所以將文本轉化為數值 node_weight = np.array(node_weight) print("node weight", node_weight) node_weight_float = [ float(x) for x in node_weight ] max_node_weight = max(node_weight_float) min_node_weight = min(node_weight_float)#定義node 的label node_label = [n[1] for n in nodes]#將node的屬性以字典的形式儲存 temp_attrs = [n[3:7] for n in nodes] #這里儲存的信息是為了畫pie圖 attrs = dict(zip(node_names,temp_attrs)) #組成字典 print(attrs)######讀取edge表 with open('friend_edge.csv', 'r', encoding='UTF-8') as edgecsv: # Open the fileedgereader = csv.reader(edgecsv) # Read the csvedges_all = [tuple(e) for e in edgereader][1:] # Retrieve the data print(edges_all) edges = [i[0:2][::-1] for i in edges_all] #提取前兩列的數據 print(edges)############################################################################## ################################# 繪制network ################################ ############################################################################## ######設置畫布大小,數值越大,后面畫的像素越高、越清晰 plt.figure(4,figsize=(50,40)) ###### make graph G = nx.DiGraph() #這里一定要選擇有向圖,后面才可以畫出curve G.add_nodes_from(node_names,weight = node_weight ) #添加節點 G.add_edges_from(edges) #添加邊#######確定布局方式 pos = nx.spring_layout(G,k=1/3.3,scale=6,seed = 10,weight='weight') ''' 參數解釋: #k值決定了節點之間的距離,默認的設定是1/sqrt(n),n是節點數量。一般情況下,當k<1時,節點多集中在圓心內; 當k>1時,節點向圓周分布 #scale值會同比例的放大或者縮小節點的相對位置,scale<1,畫面越擠;scale>1,畫面越分散。 #seed,固定初始的隨機數的位置,若不固定,每次畫出的圖布局都不一樣,原理是spring_layout這種布局算法會初始先隨機找一個點,然后通過不斷的迭代對點的位置進行優化。 ''' ######顯示網絡圖的基本屬性 density = nx.density(G) print("Network density:", density)######繪制節點的label node_labels = dict(zip(G.nodes,node_label)) nx.draw_networkx_labels(G, pos=pos, labels = node_labels, font_size=50,alpha=0.98 ) ''' 這里font_size決定了node label 的大小 alpha 的大小決定了label的透明度 ''' ######繪制edge nx.draw_networkx_edges(G,edge_color='gray', arrowsize = 5, width=0.8, pos=pos, connectionstyle='arc3,rad=0.2')#在這里添加屬性,添加顏色和大小 print(nx.info(G)) ''' arrowsize表示有向圖里邊的箭頭的大小 connectionstyle='arc3,rad=0.2':其實設置的邊的弧度,繪制出曲線,默認是直線 ''' ######繪制pie圖 #設置pie圖里每個扇形的顏色 colors = ['orangered', 'dodgerblue', 'gold', 'darkseagreen'] #設置pie圖的legend的label labels1 = [u'Photography',u'Swimming',u'Cooking',u'Yoga'] #定義標簽b = -1 for node in G.nodes:attributes = attrs[node]attribute_float = list(map(lambda x:float(x), attributes))b = b + 1current_radius = (node_weight_float[b] - min_node_weight)*0.5/(max_node_weight-min_node_weight) + 0.2'''node的weight,這里設置一個線性函數,調整node size的相對大小,并將該數值賦值給pie圖的半徑'''a = plt.pie(attribute_float, # center=pos[node], #pie圖的位置就是node的位置labels=labels1, #給pie圖添加label,由于所有pie圖的label是一致的,所以只需繪制一次legend即可colors = colors ,pctdistance = 0.6,textprops = { 'fontsize':0}, #set label fontsize to zero so it won't showradius=current_radius, #調整pie圖的半徑wedgeprops={'alpha':0.9}) #調整透明度if b == 0: # only draw legend onceplt.legend(loc='upper right', prop={'size': 50}) ###設置坐標軸 ''' 坐標軸的大小一定要和網絡圖匹配,否則會導致一些node,edge或者node label 顯示不出來 ''' plt.ylim(-9.5,8) plt.xlim(-9,11)###保存圖片 plt.savefig('friend.png') #一定放在plt.show()之前 plt.show()總結
成圖
?最終的圖片是不是超美!!!不接受反駁~
network 性質?
以下是該網絡的一些基本性質,如節點個數是10個,共有50條邊,平均入度是5,出度也是5。
print(nx.info(G))
Name:?
Type: DiGraph
Number of nodes: 10
Number of edges: 50
Average in degree: ? 5.0000
Average out degree: ? 5.0000
參考
以下代碼參考鏈接:(樓主為了繪制此圖,搜索了n多鏈接,累的快要吐血,最終篩選如下有用的幾個鏈接)
- networkX包的官方說明文件,請務必詳讀!!!https://networkx.org/documentation/stable/reference/generated/networkx.drawing.layout.spring_layout.html;
- 繪制pie圖的參考文件?:https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html
- 一些其他參考:https://blog.csdn.net/u012111465/article/details/72797032
原創不易,覺得有用請點贊收藏轉發。多謝!!!
完結,撒花~
總結
以上是生活随笔為你收集整理的Python绘制节点是饼状图的社交网络图(Plot network with pie chart)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用OpenCV合成训练图片,同时生成l
- 下一篇: 微信小程序学习第8天——自定义组件的数据