本次筆記內(nèi)容:
- 網(wǎng)絡(luò)圖的簡(jiǎn)要結(jié)構(gòu)
- 以相關(guān)系數(shù)表為例:networkx構(gòu)建網(wǎng)絡(luò)結(jié)構(gòu)
- Cytoscape可視化網(wǎng)絡(luò)圖
- co-XXX network
網(wǎng)絡(luò)圖的簡(jiǎn)要結(jié)構(gòu)
網(wǎng)絡(luò)結(jié)構(gòu)由點(diǎn)及連接點(diǎn)的線組成,反映了點(diǎn)所代表的元素之間的關(guān)系。網(wǎng)絡(luò)圖使得我們對(duì)各元素之間的關(guān)系有一個(gè)直觀的認(rèn)識(shí)。
- 點(diǎn):
點(diǎn)的大小可以表示該元素所包含的樣本數(shù)/數(shù)值大小等;
點(diǎn)的顏色及形狀可以表示該元素的類(lèi)別屬性。 - 線:
線的粗細(xì)可以表示兩元素之間關(guān)聯(lián)的大?。ū热缦嚓P(guān)系數(shù)的大?。?;
線的顏色可以表示兩元素之間關(guān)聯(lián)的方向(比如相關(guān)系數(shù)的正負(fù)),或者你自定義的某些類(lèi)別;
線可以包含箭頭,同樣可以表明方向;
線的形狀可以為直線或曲線,曲線可以在兩個(gè)元素之間不重合。以上需根據(jù)具體科學(xué)目的自定義其屬性。
以相關(guān)系數(shù)表為例network繪制網(wǎng)絡(luò)圖
這里用的networkx是Python一個(gè)模塊。我們用它來(lái)定義構(gòu)成網(wǎng)絡(luò)圖的點(diǎn),線,及點(diǎn)線的各種屬性。
安裝networkx : $ pip install networkx
以下為一個(gè)基礎(chǔ)示例,可以快速了解一下:
import networkx as nx
import matplotlib.pylab as plt
G = nx.Graph() # 生成一個(gè)空的network對(duì)象
G.add_node('a',group='t1', your_group='your_group1' ) # 添加每個(gè)點(diǎn)(node), group就是node的類(lèi)別屬性,你可以自定義每個(gè)node的屬性。
G.add_node('b',group='t1', )
G.add_node('c',group='t2')
print(G.node(data=True))
# 點(diǎn)以list儲(chǔ)存,是有順序的,其屬性以字典儲(chǔ)存。
# [('a', {'group': 't1', 'your_group': 'your_group1'}), ('b', {'group': 't1'}), ('c', {'group': 't2'})]
G.add_edge('a', 'b', weight=0.5,graphics={'fill' : '#CD5C5C'}) # 添加邊,a,b兩點(diǎn)之間的連線weight為0.5,填充顏色為#CD5C5C
print(G.edge(data=True))
# [('a', 'b', {'weight': 0.5, 'graphics': {'fill': '#CD5C5C'}})]
# 注意以上network各屬性的存儲(chǔ)方式,可以通過(guò)for循環(huán)來(lái)批量設(shè)置點(diǎn)和線的屬性。
node_color = ['yellow','yellow','orange']
nx.draw(G,node_color=node_color,node_size=200, with_labels=True)
plt.show()
# 可以結(jié)合matplotlib在python里可視化
nx.write_gml(G, 'XXX.gml')
# 網(wǎng)絡(luò)結(jié)構(gòu)可以存儲(chǔ)為.gml等格式,作為Cytoscape的input
# 另外,gml格式不允許類(lèi)別名稱出現(xiàn)下劃線‘_’,即group不可以是group_a這樣的寫(xiě)法。

以下以sklearn中 wine recognition dataset為例,
先構(gòu)建相關(guān)系數(shù)矩陣:
import networkx as nx
import matplotlib.pylab as plt
from sklearn import datasets
import pandas as pd
from scipy.stats.stats import pearsonr # 用來(lái)計(jì)算pearson相關(guān)系數(shù)
wine_data = datasets.load_wine()
wine_df = pd.DataFrame(data=wine_data['data'],columns=wine_data['feature_names'])
wine_df.head() # 行為samples, 列為features
> alcohol malic_acid ash alcalinity_of_ash magnesium total_phenols flavanoids nonflavanoid_phenols proanthocyanins color_intensity hue od280/od315_of_diluted_wines proline
0 14.23 1.71 2.43 15.6 127.0 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065.0
1 13.20 1.78 2.14 11.2 100.0 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050.0
2 13.16 2.36 2.67 18.6 101.0 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185.0
3 14.37 1.95 2.50 16.8 113.0 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480.0
4 13.24 2.59 2.87 21.0 118.0 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735.0
corr = pd.DataFrame()
corr_p = pd.DataFrame()
for i in wine_df.columns:
for j in wine_df.columns:
corr.loc[i,j] = pearsonr(wine_df[i], wine_df[j])[0]
corr_p.loc[i,j] = pearsonr(wine_df[i], wine_df[j])[1]
corr.head() # 是一個(gè)wine_df.columns對(duì)wine_df.columns的對(duì)稱table
tep = abs(corr_p.values) < 0.05
temp.sum() # 135,p<0.05的不少
然后構(gòu)建網(wǎng)絡(luò)結(jié)構(gòu):
def dataframe_to_tp(corr, row, corr_pvalue):
'''
:param corr: corr df
:param row: like "alcohol" (single OTU index, for loop use)
:param corr_pvalue: corr_p df
:return: row_list: [('alcohol','ash', cor('alcohol','ash'))]
很冗余,能寫(xiě)的更elegent請(qǐng)告訴我
'''
row_list = []
for col in list(corr.columns):
if (corr_pvalue.loc[row, col] < 0.05) & (abs(corr).loc[row,col] > 0.5):
tp = (row, col, corr.loc[row, col])
row_list.append(tp)
else:
pass
for i in row_list:
if i[0] == i[1]: # 把那些自己對(duì)自己的去掉
row_list.remove(i)
return row_list
print(dataframe_to_tp(corr, 'alcohol',corr_p))
# [('alcohol', 'color_intensity', 0.5463641950837036), ('alcohol', 'proline', 0.6437200371782135)]
raw_edges_list = [] # [(node1,node2,weight),(...),()]
for row in corr.index.values:
raw_edges_list += dataframe_to_tp(corr, row, corr_p)
# 這時(shí)候的raw_edges_list是含有重復(fù)edges的,即包含(node1,node2,XX)和(node2,node1,XX)
# 后面的操作直到edge_weight_final都是為了去除重復(fù)edges...可以說(shuō)是相當(dāng)ugly了,如果有什么好的辦法請(qǐng)告訴我...
edge_dict = {}
for tp in raw_edges_list:
edge_dict[(tp[0],tp[1])] = tp[2]
not_d_edge = []
for i in [set(i) for i in edge_dict.keys()]:
if i not in not_d_edge:
not_d_edge.append(i)
edge_weight_final = []
for edge in not_d_edge:
final_edge = tuple(edge) + (edge_dict[tuple(edge)],)
edge_weight_final.append(final_edge)
print(edge_weight_final) #看一下
# [('alcohol', 'color_intensity', 0.5463641950837036),
# ('alcohol', 'proline', 0.6437200371782135),
# ('hue', 'malic_acid', -0.5612956886649448),
# ('total_phenols', 'flavanoids', 0.8645635000951146), # ('proanthocyanins', 'total_phenols', 0.6124130837800361),
# ('od280/od315_of_diluted_wines', 'total_phenols', 0.699949364791186),
# ('nonflavanoid_phenols', 'flavanoids', -0.5378996119051982),
# ('proanthocyanins', 'flavanoids', 0.6526917686075154),
# ('hue', 'flavanoids', 0.5434785664899897),
# ('od280/od315_of_diluted_wines', 'flavanoids', 0.7871939018669516),
# ('nonflavanoid_phenols', 'od280/od315_of_diluted_wines', -0.5032695960789115),
# ('od280/od315_of_diluted_wines', 'proanthocyanins', 0.5190670956825231),
# ('hue', 'color_intensity', -0.5218131932287576),
# ('od280/od315_of_diluted_wines', 'hue', 0.5654682931826592)]
# 把做好的tuple list用于構(gòu)建網(wǎng)絡(luò):
G = nx.Graph()
# G.add_weighted_edges_from(weighted_edges_list) 這樣也可以
for tp in weighted_edges_list:
node1 = tp[0]
node2 = tp[1]
weight = tp[2]
if weight > 0: # 給正負(fù)相關(guān)系數(shù)添上不同的顏色
G.add_edge(node1, node2, weight=abs(weight), graphics={'fill':'#CD5C5C'})
else:
G.add_edge(node1, node2, weight=abs(weight), graphics={'fill':'#4682B4'})
# 畫(huà)圖
edge_width = [G[u][v]['weight']*10 for u,v in G.edges()]
color = [G[u][v]['graphics']['fill'] for u,v in G.edges()]
nx.draw(G,width=edge_width, pos = nx.circular_layout(G), edge_color=color, with_labels=True)
# 如下圖所示
nx.write_gml(G, 'XXX/wine.gml')
# wine.gml就是網(wǎng)絡(luò)結(jié)構(gòu)了,接下來(lái)把它導(dǎo)入Cytoscape可視化
線的粗細(xì)為相關(guān)系數(shù)的大?。ú惶黠@,因?yàn)橄嚓P(guān)系數(shù)差不多),紅色為正相關(guān),藍(lán)色為負(fù)相關(guān)。networkx確實(shí)也可以很好的可視化網(wǎng)絡(luò)圖,但Cytoscape的功能更完備。

Cytoscape可視化網(wǎng)絡(luò)圖

Cytoscape是一個(gè)免費(fèi)軟件,可以在win,macOS及Linux系統(tǒng)上使用。其下載和安裝對(duì)java有要求,可以參考其官網(wǎng)下載指南。
安裝好Cytoscape后,打開(kāi)并導(dǎo)入(import)上述構(gòu)建的.gml格式網(wǎng)絡(luò)結(jié)構(gòu):

得到:

設(shè)置layout : layout是用算法將網(wǎng)絡(luò)的形態(tài)改變,調(diào)整成合適的樣子。以下為兩種不同layout的效果??梢钥吹轿覀?cè)赑ython里設(shè)置的edges顏色在這里出現(xiàn)了。
Control Panel中Style欄用于設(shè)置字體大小,node框性狀及顏色,如果node有分組信息可以按組批量設(shè)置。建議自己都點(diǎn)著試試,很容易上手。
Table Panel中包括node table, edge table和network table。
有一篇超級(jí)詳細(xì)的Cytoscape中文攻略可以參考。


按照weight的大小定義線的width,注意在style的edge欄里設(shè)置。

在style里還可以設(shè)置網(wǎng)絡(luò)圖的appearance:

導(dǎo)出為pdf:

co-XXX network
現(xiàn)在好像很流行畫(huà)co-abundance/co-occurrence network,如果你找出來(lái)組間差異物種有很多,想看看這么多差異物種之間有沒(méi)有什么關(guān)聯(lián)。于是可以畫(huà)個(gè)co-XXX network。比方說(shuō)如下兩篇文章的圖:


需要注意的是這種圖是把兩個(gè)(或多個(gè))network合并在一起繪制的。兩點(diǎn)之間除了直線連接還有曲線(避免與直線重合)。這意味著兩點(diǎn)之間不只一個(gè)edge. 上述示例代碼仍然適用,但需要使用MultiGraph()
import networkx as nx
Gm = nx.MultiGraph()
Gm.add_edge('XXX from corr_1')
Gm.add_edge('XXX from corr_2')
# 具體內(nèi)容和上述示例代碼是差不多的
在Cytoscape中,如果需要設(shè)置edge的彎曲,在Stlye,Edge頁(yè)面,點(diǎn)擊Properties展開(kāi)按鈕,找到Bend, 可以按照提示設(shè)置邊的曲率。
最后跑個(gè)題,安利一下Atom, 一個(gè)text editor. 在win上用的話可以扔掉Notepad++了。而且我感覺(jué)沒(méi)用到很高級(jí)的功能的話,pycharm都可以扔掉了...R, python, js等各種語(yǔ)言的代碼都可以往里塞,可以自行下載海量packages來(lái)滿足五花八門(mén)的需求,界面如下:

像ipython一樣逐行輸出:

圖也可以plot出來(lái),在代表顏色的字符串上直接print出顏色(太炫了?。】催@個(gè)Q萌的界面!顏控愛(ài)了!!(′Д` ))

參考:
networkx官方tutorial
network.draw的細(xì)節(jié)
一篇超級(jí)詳細(xì)的Cytoscape中文攻略
Cytoscape tutorials官網(wǎng)
知乎專(zhuān)欄上一個(gè)atom的介紹
Atom官方使用指南