【python資料探勘課程】十七.社交網路Networkx庫分析人物關係(初識篇)

Eastmount發表於2017-11-05

這是《Python資料探勘課程》系列文章,也是我大資料金融學院上課的部分內容。本章主要講述複雜網路或社交網路基礎知識,通過Networkx擴充套件包繪製人物關係,並分析了班級學生的關係學院資訊。本篇文章為初始篇,基礎文章希望對你有所幫助,如果文章中存在錯誤或不足支援,還請海涵~
自己真的太忙了,只能擠午休的時間學習新知識,與天鬥其樂無窮。


前文推薦:
【Python資料探勘課程】一.安裝Python及爬蟲入門介紹
【Python資料探勘課程】二.Kmeans聚類資料分析及Anaconda介紹
【Python資料探勘課程】三.Kmeans聚類程式碼實現、作業及優化
【Python資料探勘課程】四.決策樹DTC資料分析及鳶尾資料集分析
【Python資料探勘課程】五.線性迴歸知識及預測糖尿病例項
【Python資料探勘課程】六.Numpy、Pandas和Matplotlib包基礎知識
【Python資料探勘課程】七.PCA降維操作及subplot子圖繪製
【Python資料探勘課程】八.關聯規則挖掘及Apriori實現購物推薦
【Python資料探勘課程】九.迴歸模型LinearRegression簡單分析氧化物資料
【python資料探勘課程】十.Pandas、Matplotlib、PCA繪圖實用程式碼補充
【python資料探勘課程】十一.Pandas、Matplotlib結合SQL語句視覺化分析
【python資料探勘課程】十二.Pandas、Matplotlib結合SQL語句對比圖分析
【python資料探勘課程】十三.WordCloud詞雲配置過程及詞頻分析
【python資料探勘課程】十四.Scipy呼叫curve_fit實現曲線擬合
【python資料探勘課程】十五.Matplotlib呼叫imshow()函式繪製熱圖
【python資料探勘課程】十六.邏輯迴歸LogisticRegression分析鳶尾花資料



一. 社交網路基礎


近年來,隨著社交網路的興起,比如Facebook、微博微信、搜尋引擎、知識圖譜等領域都涉及到了社交網路技術。
網路採用一種關係為中心的世界觀,通過利用人與人間關係的現有資料結構(社交網路),可以利用聚類等技術發現社群,洞察圖中重要成員的作用,甚至通過關係推斷來進行行為預測。

網路與圖論密切相關,圖論起源於1735年尤拉對七橋問題的研究。一個圖是由一組頂點(結點)和它們間的連線(關係或邊)構成的網路的負號表示。圖定義為G={V, E},一個由有限多結點V形成的集合和不分順序的二元組數對{u, v}形成的邊E。如下圖所示:



圖可以是有方向的或無方向的,通常可以用鄰接矩陣表示。推薦大家簡單複習下圖論知識,這裡作者主要通過Python的Networkx擴充套件包講解基礎用法。


二. Networkx基礎知識


Networkx是一個用來建立、操作、研究複雜網路結構的Python擴充套件包。它支援圖的快速建立,同時常用的圖演算法。同時Networkx擴充套件包完善了Python的科學計算工具集,如Scipy、Numpy等。

1.安裝過程
安裝主要呼叫PIP命令,作者這裡使用Anaconda軟體已經整合了該擴充套件包。

pip install networkx  --安裝包
pip install --upgrade networkx  --更新升級包
pip uninstall networkx  --解除安裝包

2.基礎程式碼
下面首先給大家看一個Networkx呼叫draw(G)繪圖的程式碼。

# -*- coding: utf-8 -*-
import networkx as nx
import matplotlib.pyplot as plt

#定義有向圖
DG = nx.DiGraph() 
#新增五個節點(列表)
DG.add_nodes_from(['A', 'B', 'C', 'D', 'E'])
print DG.nodes()
#新增邊(列表)
DG.add_edges_from([('A', 'B'), ('A', 'C'), ('A', 'D'), ('D','A'),('E','A'),('E','D')])
print DG.edges()
#繪製圖形 設定節點名顯示\節點大小\節點顏色
colors = ['red', 'green', 'blue', 'yellow']
nx.draw(DG,with_labels=True, node_size=900, node_color = colors)
plt.show()
執行程式碼如下圖所示:

3.Networkx詳細介紹

(1) 匯入擴充套件包建立無多重邊有向圖
    import networkx as nx
    DG = nx.DiGraph()
圖物件主要包括點和邊,Networkx建立圖包括四類:Graph無多重邊無向圖,DiGraph無多重邊有向圖,MultiGraph有多重邊無向圖,MultiDiGraph有多重邊有向圖。 

(2) 增加點,採用序列增加五個點
    DG.add_nodes_from(['A', 'B', 'C', 'D', 'E'])
增加點可以通過G.add_node(1)、G.add_node("first_node")函式增加一個點,也可以呼叫DG.add_nodes_from([1,2,3])、DG.add_nodes_from(D)函式批量增加多個點。刪除點呼叫DG.remove_node(1)或DG.remove_nodes_from([1,2,3])實現。


(3) 增加邊,採用序列增加多條邊

    DG.add_edges_from([('A', 'B'), ('A', 'C'), ('A', 'D'), ('D','A')])
增加一條邊可以呼叫DG.add_edge(1,2)函式,表示在1和2之間增加一個點,從1指向2;也可以定義 e=(1,2) 邊,在呼叫DG.add_edge(*e)函式實現,注意*用來獲取元組(1,2)中的元素。增加多條表則使用DG.add_edges+from([(1,2), (2,3)])函式實現。
同理,刪除邊採用remove_edge(1,2)函式或remove_edges_from(list)實現。


(4) 訪問點和邊

    DG.nodes()  #訪問點,返回結果:['A', 'C', 'B', 'E', 'D']
    DG.edges()  #訪問邊,返回結果:[('A', 'C'), ('A', 'B'), .... , ('D', 'A')]
    DG.node['A']         #返回包含點和邊的列表
    DG.edge['A']['B']   #f返回包含兩個key之間的邊


(5) 檢視點和邊的數量

    DG.number_of_nodes()  #檢視點的數量,返回結果:5
    DG.number_of_edges()  #檢視邊的數量,返回結果:6
    DG.neighbors('A')          #所有與A連通的點,返回結果:['C', 'B', 'D']
    DG['A']  #所有與A相連邊的資訊,{'C': {}, 'B': {}, 'D': {}},未設定屬性


(6) 設定屬性

可以給圖、點、邊賦予各種屬性,其中權值屬性最為常見,如權重、頻率等。
    DG.add_node('A', time='5s')
    DG.add_nodes_from([1,2,3],time='5s')
    DG.add_nodes_from([(1,{'time':'5s'}), (2,{'time':'4s'})])  #元組列表
    DG.node['A']  #訪問
    DG.add_edges_from([(1,2),(3,4)], color='red')

4.draw繪圖
繪製圖只要呼叫draw(G)函式,比如:
    nx.draw(DG,with_labels=True, node_size=900, node_color = colors)
引數pos表示佈局,包括spring_layout、random_layout、circular_layout、shell_layout四種型別,如pos=nx.random_layout(G);引數node_color='b'設定節點顏色;edge_color='r'設定邊顏色;with_labels顯示節點;font_size設定大小;node_size=20設定節點大小。
    circular_layout:節點在一個圓環上均勻分佈 
    random_layout:節點隨機分佈 
    shell_layout:節點在同心圓上分佈 
    spring_layout: 用Fruchterman-Reingold演算法排列節點

同時,補充一個更好的繪製圖形函式:

pos=nx.random_layout(G)
nx.draw_networkx_nodes(G, pos, alpha=0.2,node_size=1200,node_color=colors)
nx.draw_networkx_edges(G, pos, node_color='r', alpha=0.3)
nx.draw_networkx_labels(G, pos, font_family='sans-serif', alpha=0.5) 


三. 分析人物關係網路

寫到這裡正式開始我們的人物關係分析,首先統計了我這門課程的105個學生資訊,如下表所示,主要包括姓名、性別、學院、班級、宿舍等內容,這裡主要根據學院資訊簡歷人物關係。



步驟如下:
1.呼叫Pandas庫讀取data.csv檔案,並獲取學生姓名,姓名儲存在一個陣列裡;
2.計算各個學生的共現矩陣,比如A和B都是同一個學院的,則共現依次,權重加1。注意,這裡的學生來自各個學院,分析他們學院之間的關係;
3.將共現矩陣儲存至word_node.txt檔案中,格式為"學生A 學生B 共現詞頻";
4.讀取word_node.txt檔案,採用空格分割,繪製對應關係圖,如果學生A和學生B共同出現,則建立一條邊,表示存在關係。類似的,如果做小說或電視人物關係分析,如果人物某一章同時出現,則認為存在關係建立一條邊。
5.呼叫Networkx庫繪製圖形。

完整程式碼如下:

# -*- coding: utf-8 -*-
"""
Created on Thu Nov 02 10:33:58 2017
@author: eastmount CSDN 楊秀璋
"""
import pandas as pd
import numpy as np
import codecs
import networkx as nx
import matplotlib.pyplot as plt


""" 第一步:讀取資料並獲取姓名 """
data = pd.read_csv("data.csv",encoding ="gb2312") #中文亂碼
print data[:4]
print data[u'姓名'] #獲取某一列資料
print type(data[u'姓名'])
name = []
for n in data[u'姓名']:
    name.append(n)
print name[0]


""" 第二步:計算共現矩陣 定義函式實現 """
a = np.zeros([2,3])
print a
print len(name)
word_vector = np.zeros([len(name),len(name)]) #共現矩陣

#1.計算學院共線矩陣
i = 0
while i<len(name):  #len(name)
    academy1 = data[u'學院'][i]
    j = i + 1
    while j<len(name):
        academy2 = data[u'學院'][j]
        if academy1==academy2: #學院相同
            word_vector[i][j] += 1
            word_vector[j][i] += 1
        j = j + 1   
    i = i + 1
print word_vector
np_data = np.array(word_vector)  #矩陣寫入檔案
pd_data = pd.DataFrame(np_data)
pd_data.to_csv('result.csv')
#2.計算大資料金融班級共線矩陣
#3.計算性別共線矩陣
#4.計算宿舍樓層共線矩陣
"""
i = 0
while i<len(name):  #len(name)
    academy1 = data[u'宿舍樓層'][i]
    j = i + 1
    while j<len(name):
        academy2 = data[u'宿舍樓層'][j]
        if academy1==academy2: #相同
            word_vector[i][j] += 1
            word_vector[j][i] += 1
        j = j + 1   
    i = i + 1
print word_vector
"""


""" 第三步:共現矩陣計算(學生1 學生2 共現詞頻)檔案 """
words = codecs.open("word_node.txt", "a+", "utf-8")
i = 0
while i<len(name):  #len(name)
    student1 = name[i]
    j = i + 1
    while j<len(name):
        student2 = name[j]
        #判斷學生是否共現 共現詞頻不為0則加入
        if word_vector[i][j]>0:
            words.write(student1 + " " + student2 + " " 
                + str(word_vector[i][j]) + "\r\n")
        j = j + 1
    i = i + 1
words.close()


""" 第四步:圖形生成 """
a = []
f = codecs.open('word_node.txt','r','utf-8')
line = f.readline()
print line
i = 0
A = []
B = []
while line!="":
    a.append(line.split())   #儲存檔案是以空格分離的
    print a[i][0],a[i][1]
    A.append(a[i][0])
    B.append(a[i][1])
    i = i + 1
    line = f.readline()
elem_dic = tuple(zip(A,B)) 
print type(elem_dic)
print list(elem_dic)
f.close()

import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['SimHei']   
matplotlib.rcParams['font.family']='sans-serif'

colors = ["red","green","blue","yellow"]
G = nx.Graph()
G.add_edges_from(list(elem_dic))
#nx.draw(G,with_labels=True,pos=nx.random_layout(G),font_size=12,node_size=2000,node_color=colors) #alpha=0.3
#pos=nx.spring_layout(G,iterations=50)
pos=nx.random_layout(G)
nx.draw_networkx_nodes(G, pos, alpha=0.2,node_size=1200,node_color=colors)
nx.draw_networkx_edges(G, pos, node_color='r', alpha=0.3) #style='dashed'
nx.draw_networkx_labels(G, pos, font_family='sans-serif', alpha=0.5) #font_size=5
plt.show()
其中 word_node.txt 檔案輸出如下所示:
楊宜波 陳杰 1.0
楊宜波  包承菊 1.0
楊宜波 劉天華 1.0
楊宜波 劉紫傑 1.0
楊宜波 歐守傑 1.0
楊宜波 塗書發 1.0
楊宜波 雷琳 1.0
楊宜波 楊美 1.0
張濤 胡垠 1.0
張濤 班敬凱 1.0
張濤 李藍 1.0
張濤 曾偉 1.0
張濤 楊傑 1.0
張濤 穆佑湖 1.0
張濤 吳貴禹 1.0
張濤 鄧迪 1.0
張濤 張軍 1.0
spring_layout輸出圖形如下所示,可以看到聚集在一起的為同一個學院學生。


random_layout輸出圖形如下所示:

circular_layout輸出圖形如下所示,將人物圍城一圈:


資料集建議讀者自己去建立,學生資料保密,同時可以根據各種關係建立人物關係,共現矩陣也可以有不同的計算方法,推薦讀者下來研究。最後作者也是剛剛學習這類知識,一起進步,希望文章對你有所幫助,尤其是我的學生,如果文章中存在錯誤或不足之處,還請海涵。給綠么準備驚喜中~

參考文獻:
《資料科學實戰手冊(R+Python)》 郝智恆 - 第8章
python networkx 包繪製複雜網路關係圖 - 簡書(Forget_ever)
python複雜網路分析庫NetworkX - 部落格園(jihite)
[Python]networkx入門 - CSDN(ice110956)
基於共現發現人物關係的python實現 - 知乎(鄧旭東)
文字分析之製作網路關係圖鄧旭東HIT - 知乎(鄧旭東大神)
python簡單實戰專案:《冰與火之歌1-5》角色關係圖譜構建——人物關係視覺化
python學習筆記(2)--Networkx畫圖 - CSDN(Leige_Smart)


(By:Eastmount 2017-11-5 深夜12點  http://blog.csdn.net/eastmount/ )




相關文章