Saltar al contenido

Mejora del diseño de gráficos de Python NetworkX

Si encuentras algo que te causa duda puedes dejarlo en la sección de comentarios y haremos todo lo necesario de ayudarte tan rápido como podamos.

Solución:

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

He tenido un buen éxito con neato pero las otras posibles entradas 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 primavera”. Esta es la herramienta predeterminada para usar si el gráfico no es demasiado grande (alrededor de 100 nodos) y no sabe nada más al respecto. Neato intenta minimizar una función de energía global, que es equivalente al escalado multidimensional estadístico.

  • fdp – Diseños de “modelo de resorte” similares a los de neato, pero lo hace reduciendo las 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, según 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 diagramas de múltiples estructuras cíclicas, como ciertas redes de telecomunicaciones.

En general, el dibujo de gráficos es un problema difícil. Si estos algoritmos no son suficientes, tendrá que escribir los suyos propios o hacer que networkx dibuje partes individualmente.

Encontré que esto es útil para visualizar rápidamente los datos de interacción (aquí, genes) obtenidos como un archivo CSV.

Archivo de datos [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.7 venv

import networkx as nx
import matplotlib.pyplot as plt
G = nx.read_edgelist("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

ACTUALIZAR

Esto solía funcionar (2018-03), pero ahora (2019-12) da un pygraphviz error de importación:

from networkx.drawing.nx_agraph import graphviz_layout

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)

    Traceback (most recent call last):
    ...
    ImportError: libpython3.7m.so.1.0: cannot open shared object file:
      No such file or directory
    During handling of the above exception, another exception occurred:
      Traceback (most recent call last):
    ...
    ImportError: ('requires pygraphviz ', 'http://pygraphviz.github.io/')

SOLUCIÓN

Fuera de Python (en el indicador de la terminal venv: $) Instalar en pc pydot.

pip install pydot

De vuelta en Python, ejecute el siguiente código.

import warnings
warnings.filterwarnings("ignore", category=UserWarning)

import networkx as nx
import matplotlib.pyplot as plt

G = nx.read_edgelist("a.csv", delimiter=",")
# For a DiGraph() [directed edges; not shown]:
#   G = nx.read_edgelist("a.csv", delimiter=",", create_using=nx.DiGraph)

nx.draw(G, pos = nx.nx_pydot.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 attached

El principal cambio fue reemplazar

nx.draw(G, pos = graphviz_layout(G), ...)

con

nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), ...)

Referencias

Eliminar la advertencia de depreciación de matplotlib para que no se muestre

¿Qué podría hacer que NetworkX y PyGraphViz funcionen bien solos pero no juntos?

  • Específicamente: https://stackoverflow.com/a/40750101/1904943

Disposición de la parcela mejorada

Es difícil disminuir la congestión en estos static gráficos networkx / matplotlib; una solución alternativa es aumentar el tamaño de la figura, según esta Q / A de StackOverflow: Imagen de alta resolución de un gráfico usando NetworkX y Matplotlib:

plt.figure(figsize=(20,14))
# 

nx.draw(G, pos = nx.nx_pydot.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

Para restablecer el tamaño de la figura de salida al valor predeterminado del sistema:

plt.figure()
# 

Bono: camino más corto

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


plot1.pngplot1.png

plot2.pngplot2.png


Aunque no hice esto aquí, si desea agregar bordes de nodo y engrosar las líneas del borde del nodo (grosor del borde del nodo: linewidths), Haz lo siguiente.

nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), 
    node_size=1200, node_color='lightblue', linewidths=2.0, 
    font_size=10, font_weight='bold', with_labels=True)
# Get current axis:
ax = plt.gca()
ax.collections[0].set_edgecolor('r')
# r : red (can also use #FF0000) | b : black (can also use #000000) | ...
plt.show()

Tiene muchos 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 usabas spring_layout. Te sugiero que lo intentes de nuevo, pero esta vez usando el weight attribute 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 el parámetro scale para aumentar la distancia global entre los nodos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *