Подтвердить что ты не робот

Улучшение макета графика Python NetworkX

У меня возникают некоторые проблемы с визуализацией графиков, созданных с помощью python-networkx, я хочу уменьшить количество помех и регулировать расстояние между узлами (я также попробовал spring_layout, он просто выводит узлы эллиптически), Пожалуйста, порекомендуйте. enter image description here

Части кода:

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)
4b9b3361

Ответ 1

В networkx стоит проверить алгоритмы рисования графа, предоставляемые graphviz через nx.graphviz_layout.

Я имел хороший успех с neato но другие возможные входы

  • dot - "иерархические" или слоистые рисунки ориентированных графов. Этот инструмент используется по умолчанию, если ребра имеют направленность.

  • neato - neato "пружинной модели". Это инструмент по умолчанию, который используется, если график не слишком большой (около 100 узлов), и вы больше ничего о нем не знаете. Neato пытается минимизировать глобальную энергетическую функцию, которая эквивалентно статистическому многомерному масштабированию.

  • fdp - fdp "весенней модели", аналогичная макетам Neato, но делает это, уменьшая силы, а не работая с энергией.

  • sfdp - многомасштабная версия fdp для верстки больших графов.

  • twopi - радиальное расположение, после Грэма Уилса 97. Узлы размещаются на концентрических окружностях в зависимости от их расстояния от данного корневого узла.

  • circo - круговая схема, после Six и Tollis 99, Kauffman и Wiese 02. Это подходит для определенных диаграмм множественных циклических структур, таких как определенные телекоммуникационные сети.

В общем, рисование графиков является сложной проблемой. Если этих алгоритмов недостаточно, вам придется написать свой собственный или иметь отдельные части для рисования.

Ответ 2

У вас на вашем графике много данных, поэтому будет трудно удалить беспорядок.

Я предлагаю вам использовать любой стандартный макет. Вы сказали, что используете spring_layout. Я предлагаю вам попробовать еще раз, но на этот раз с помощью атрибута weight при добавлении ребер.

Например:

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()

Кроме того, вы можете использовать параметр scale для увеличения глобального расстояния между узлами.

Ответ 3

Я обнаружил, что это полезно для быстрой визуализации данных взаимодействия, полученных в виде файла CSV из PostgreSQL. [Вывод ниже переформатирован для удобства чтения.]

## 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:

[[email protected] ~]$ 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

Трудно уменьшить скопление на этих статических графиках networkx/matplotlib; один из обходных путей - увеличить размер рисунка, в соответствии с этим StackOverflow Q/A: изображение графика с высоким разрешением с использованием NetworkX и Matplotlib:

>>> plt.figure(figsize=(20,14))
  <matplotlib.figure.Figure object at 0x7f1b65ea5e80>

>>> 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()
  <matplotlib.figure.Figure object at 0x7f1b454f1588>

plot1.png plot1.png

plot2.png plot2.png

Бонус - кратчайший путь:

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

Ответ 4

Чтобы ответить на вопрос о том, как регулировать расстояние между узлами, я расширяю Hooked answer:

Если вы нарисуете график через бэкэнд Graphviz и когда вы используете алгоритм fdp, вы можете отрегулировать расстояние между узлами по edge len.

Вот пример кода, как рисовать график G и сохранять в файле Graphviz gvfile с более широким расстоянием между узлами (расстояние по умолчанию для fdp равно 0.3):

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

Два комментария:

  • Обычно рекомендуется отрегулировать len с количеством узлов в графике.
  • Атрибут len распознается только с помощью алгоритмов fdp и neato, но не, например. с помощью алгоритма sfdp.