本次笔记内容:
网络图的简要结构 以相关系数表为例:networkx构建网络结构 Cytoscape可视化网络图 co-XXX network 网络图的简要结构
网络结构由点及连接点的线组成,反映了点所代表的元素之间的关系。网络图使得我们对各元素之间的关系有一个直观的认识。
点的大小可以表示该元素所包含的样本数/数值大小等;
点的颜色及形状可以表示该元素的类别属性。 线的粗细可以表示两元素之间关联的大小(比如相关系数的大小);
线的颜色可以表示两元素之间关联的方向(比如相关系数的正负),或者你自定义的某些类别;
线可以包含箭头,同样可以表明方向;
线的形状可以为直线或曲线,曲线可以在两个元素之间不重合。以上需根据具体科学目的自定义其属性。以相关系数表为例network绘制网络图
这里用的networkx是 Python 一个模块。我们用它来定义构成网络图的点,线,及点线的各种属性。
安装networkx :$ pip install networkx
以下为一个基础示例,可以快速了解一下:
import networkx as nx import matplotlib.pylab as plt G = nx.Graph() # 生成一个空的network对象 G.add_node('a',group='t1', your_group='your_group1' ) # 添加每个点(node), group就是node的类别属性,你可以自定义每个node的属性。 G.add_node('b',group='t1', ) G.add_node('c',group='t2') print(G.node(data=True)) # 点以list储存,是有顺序的,其属性以字典储存。 # [('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两点之间的连线weight为0.5,填充颜色为#CD5C5C print(G.edge(data=True)) # [('a', 'b', {'weight': 0.5, 'graphics': {'fill': '#CD5C5C'}})] # 注意以上network各属性的存储方式,可以通过for循环来批量设置点和线的属性。 node_color = ['yellow','yellow','orange'] nx.draw(G,node_color=node_color,node_size=200, with_labels=True) plt.show() # 可以结合matplotlib在python里可视化 nx.write_gml(G, 'XXX.gml') # 网络结构可以存储为.gml等格式,作为Cytoscape的input # 另外,gml格式不允许类别名称出现下划线‘_’,即group不可以是group_a这样的写法。 from sklearn import datasets import pandas as pd from scipy.stats.stats import pearsonr # 用来计算pearson相关系数 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() # 是一个wine_df.columns对wine_df.columns的对称table tep = abs(corr_p.values) < 0.05 temp.sum() # 135,p<0.05的不少
然后构建网络结构:
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'))] 很冗余,能写的更elegent请告诉我 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: for i in row_list: if i[0] == i[1]: # 把那些自己对自己的去掉 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) # 这时候的raw_edges_list是含有重复edges的,即包含(node1,node2,XX)和(node2,node1,XX) # 后面的操作直到edge_weight_final都是为了去除重复edges...可以说是相当ugly了,如果有什么好的办法请告诉我... 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 = 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: # 给正负相关系数添上不同的颜色 G.add_edge(node1, node2, weight=abs(weight), graphics={'fill':'#CD5C5C'}) else: G.add_edge(node1, node2, weight=abs(weight), graphics={'fill':'#4682B4'}) 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就是网络结构了,接下来把它导入Cytoscape可视化
线的粗细为相关系数的大小(不太明显,因为相关系数差不多),红色为正相关,蓝色为负相关。networkx确实也可以很好的可视化网络图,但Cytoscape的功能更完备。
设置layout : layout是用算法将网络的形态改变,调整成合适的样子。以下为两种不同layout的效果。可以看到我们在Python里设置的edges颜色在这里出现了。
Control Panel中Style栏用于设置字体大小,node框性状及颜色,如果node有分组信息可以按组批量设置。建议自己都点着试试,很容易上手。
Table Panel中包括node table, edge table和network table。
有一篇超级详细的Cytoscape中文攻略可以参考。2019 Gut. Tracing the accumulation of in vivo human oral microbiota elucidates microbial community dynamics at the gateway to the GI tract需要注意的是这种图是把两个(或多个)network合并在一起绘制的。两点之间除了直线连接还有曲线(避免与直线重合)。这意味着两点之间不只一个edge. 上述示例代码仍然适用,但需要使用
MultiGraph()
import networkx as nx Gm = nx.MultiGraph() Gm.add_edge('XXX from corr_1') Gm.add_edge('XXX from corr_2') # 具体内容和上述示例代码是差不多的
在Cytoscape中,如果需要设置edge的弯曲,在Stlye,Edge页面,点击Properties展开按钮,找到Bend, 可以按照提示设置边的曲率。
最后跑个题,安利一下Atom, 一个text editor. 在win上用的话可以扔掉Notepad++了。而且我感觉没用到很高级的功能的话,pycharm都可以扔掉了...R, python, js等各种语言的代码都可以往里塞,可以自行下载海量packages来满足五花八门的需求,界面如下: