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.png
plot2.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.