Mejorando el diseño gráfico de Python NetworkX

Estoy teniendo algunos problemas para visualizar los gráficos creados con python-networkx, quiero poder reducir el desorden y regular la distancia entre los nodos (también he intentado spring_layout, simplemente establece los nodos de manera elíptica). Por favor avise. introduzca la descripción de la imagen aquí

Partes de código:

nx.draw_networkx_edges(G, pos, edgelist=predges, edge_color='red', arrows=True) nx.draw_networkx_edges(G, pos, edgelist=black_edges, arrows=False, style='dashed') # label fonts nx.draw_networkx_labels(G,pos,font_size=7,font_family='sans-serif') nx.draw_networkx_edge_labels(G,pos,q_list,label_pos=0.3) 

En networkx, vale la pena revisar los algoritmos de dibujo de gráficos proporcionados por graphviz a través de nx.graphviz_layout .

He tenido buenos resultados con neato pero los otros posibles insumos son

  • dot – dibujos “jerárquicos” o en capas de gráficos dirigidos. Esta es la herramienta predeterminada para usar si los bordes tienen direccionalidad.

  • neato – “diseños de modelo de resorte”. Esta es la herramienta predeterminada que se debe usar si el gráfico no es demasiado grande (unos 100 nodos) y no se sabe nada más sobre él. Neato intenta minimizar una función de energía global, que es Equivalente a la escala estadística multidimensional.

  • fdp : fdp “modelos de resorte” similares a los de neato, pero lo hace reduciendo fuerzas en lugar de trabajar con energía.

  • sfdp – versión multiescala de fdp para el diseño de gráficos grandes.

  • twopi – diseños radiales, después de Graham Wills 97. Los nodos se colocan en círculos concéntricos dependiendo de su distancia desde un nodo raíz dado.

  • circo – diseño circular, después de Six y Tollis 99, Kauffman y Wiese 02. Esto es adecuado para ciertos diagtwigs de múltiples estructuras cíclicas, como ciertas redes de telecomunicaciones.

En general, el dibujo gráfico es un problema difícil. Si estos algoritmos no son suficientes, deberá escribir los suyos propios o tener partes de dibujo de networkx individualmente.

Tiene una gran cantidad de datos en su gráfico, por lo que será difícil eliminar el desorden.

Le sugiero que utilice cualquier diseño estándar. Dijiste que spring_layout . Le sugiero que lo intente de nuevo, pero esta vez use el atributo de weight al agregar los bordes.

Por ejemplo:

 import networkx as nx G = nx.Graph(); G.add_node('A') G.add_node('B') G.add_node('C') G.add_node('D') G.add_edge('A','B',weight=1) G.add_edge('C','B',weight=1) G.add_edge('B','D',weight=30) pos = nx.spring_layout(G,scale=2) nx.draw(G,pos,font_size=8) plt.show() 

Además, puede utilizar la scale parámetros para boost la distancia global entre los nodos.

Descubrí que esto es útil para visualizar rápidamente los datos de interacción obtenidos como un archivo CSV de PostgreSQL. [Salida a continuación reformateada para facilitar la lectura.]

 ## PSQL ['DUMMY' DATA]: [interactions_practice]# \copy (SELECT gene_1, gene_2 FROM interactions WHERE gene_1 in (SELECT gene_2 FROM interactions)) TO '/tmp/a.csv' WITH CSV -- << note: no terminating ";" for this query ## BASH: [victoria@victoria ~]$ cat /tmp/a.csv APC,TP73 BARD1,BRCA1 BARD1,ESR1 BARD1,KRAS2 BARD1,SLC22A18 BARD1,TP53 BRCA1,BRCA2 BRCA1,CHEK2 BRCA1,MLH1 BRCA1,PHB BRCA2,CHEK2 BRCA2,TP53 CASP8,ESR1 CASP8,KRAS2 CASP8,PIK3CA CASP8,SLC22A18 CDK2,CDKN1A CHEK2,CDK2 ESR1,BRCA1 ESR1,KRAS2 ESR1,PPM1D ESR1,SLC22A18 KRAS2,BRCA1 MLH1,CHEK2 MLH1,PMS2 PIK3CA,BRCA1 PIK3CA,ESR1 PIK3CA,RB1CC1 PIK3CA,SLC22A18 PMS2,TP53 PTEN,BRCA1 PTEN,MLH3 RAD51,BRCA1 RB1CC1,SLC22A18 SLC22A18,BRCA1 TP53,PTEN ## PYTHON 3.5 VENV (ANACONDA): >>> import networkx as nx >>> import pylab as plt >>> G = nx.read_edgelist("/tmp/a.csv", delimiter=",") >>> G.edges() [('CDKN1A', 'CDK2'), ('MLH3', 'PTEN'), ('TP73', 'APC'), ('CHEK2', 'MLH1'), ('CHEK2', 'BRCA2'), ('CHEK2', 'CDK2'), ('CHEK2', 'BRCA1'), ('BRCA2', 'TP53'), ('BRCA2', 'BRCA1'), ('KRAS2', 'CASP8'), ('KRAS2', 'ESR1'), ('KRAS2', 'BRCA1'), ('KRAS2', 'BARD1'), ('PPM1D', 'ESR1'), ('BRCA1', 'PHB'), ('BRCA1', 'ESR1'), ('BRCA1', 'PIK3CA'), ('BRCA1', 'PTEN'), ('BRCA1', 'MLH1'), ('BRCA1', 'SLC22A18'), ('BRCA1', 'BARD1'), ('BRCA1', 'RAD51'), ('CASP8', 'ESR1'), ('CASP8', 'SLC22A18'), ('CASP8', 'PIK3CA'), ('TP53', 'PMS2'), ('TP53', 'PTEN'), ('TP53', 'BARD1'), ('PMS2', 'MLH1'), ('PIK3CA', 'SLC22A18'), ('PIK3CA', 'ESR1'), ('PIK3CA', 'RB1CC1'), ('SLC22A18', 'ESR1'), ('SLC22A18', 'RB1CC1'), ('SLC22A18', 'BARD1'), ('BARD1', 'ESR1')] >>> G.number_of_edges() 36 >>> G.nodes() ['CDKN1A', 'MLH3', 'TP73', 'CHEK2', 'BRCA2', 'KRAS2', 'CDK2', 'PPM1D', 'BRCA1', 'CASP8', 'TP53', 'PMS2', 'RAD51', 'PIK3CA', 'MLH1', 'SLC22A18', 'BARD1', 'PHB', 'APC', 'ESR1', 'RB1CC1', 'PTEN'] >>> G.number_of_nodes() 22 >>> from networkx.drawing.nx_agraph import graphviz_layout >>> ## nx.draw(G, pos=graphviz_layout(G)) ## DUE TO AN UNIDENTIFIED BUG, I GET THIS ERROR THE FIRST TIME RUNNING THIS ## COMMAND; JUST RE-RUN IT: >>> nx.draw(G, pos=graphviz_layout(G), node_size=1200, node_color='lightblue', linewidths=0.25, font_size=10, font_weight='bold', with_labels=True) QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries. >>> nx.draw(G, pos=graphviz_layout(G), node_size=1200, node_color='lightblue', linewidths=0.25, font_size=10, font_weight='bold', with_labels=True) >>> plt.show() ## plot1.png [opens in matplotlib popup window] attached 

Es difícil disminuir la congestión en estas plots estáticas de networkx / matplotlib; una solución es boost el tamaño de la figura, según este Q / A de StackOverflow: Imagen de alta resolución de un gráfico utilizando NetworkX y Matplotlib :

 >>> plt.figure(figsize=(20,14))  >>> nx.draw(G, pos=graphviz_layout(G), node_size=1200, node_color='lightblue', linewidths=0.25, font_size=10, font_weight='bold', with_labels=True, dpi=1000) >>> plt.show() ## plot2.png attached ## RESET OUTPUT FIGURE SIZE TO SYSTEM DEFAULT: >>> plt.figure()  

plot1.png plot1.png

plot2.png plot2.png

Bono – camino más corto:

 >>> nx.dijkstra_path(G, 'CDKN1A', 'MLH3') ['CDKN1A', 'CDK2', 'CHEK2', 'BRCA1', 'PTEN', 'MLH3'] 

Para responder a su pregunta sobre cómo regular la distancia entre nodos, amplío la respuesta de Hooked :

Si dibuja el gráfico a través del backend de Graphviz y luego utiliza el algoritmo fdp , puede ajustar la distancia entre nodos por el atributo de borde len .

Aquí un ejemplo de código, cómo dibujar un gráfico G y guardar en el archivo gvfile Graphviz con una distancia más amplia entre nodos (la distancia predeterminada para fdp es 0.3 ):

 A = nx.to_agraph(G) A.edge_attr.update(len=3) A.write(gv_file_name) 

Dos comentarios:

  1. Normalmente es recomendable ajustar len con el número de nodos en el gráfico.
  2. El atributo len solo es reconocido por el algoritmo fdp y neato , pero no por ejemplo por el algoritmo sfdp .