Как нарисовать небольшой график со структурой сообщества в networkx

В графе около 100 узлов, а количество сообществ варьируется от 5 до 20. Можно ли нарисовать граф так, чтобы узлы одного и того же сообщества были близки друг к другу?

Я пытался назначить разным сообществам разные цвета, но в моем приложении это не работает.

Я прочитал это и это, но не нашел хорошего решения.

Я использую Python 2.7.12 и newtorkx-1.11.


person user3813057    schedule 02.12.2016    source источник


Ответы (1)


Для небольшого графика я нахожу spring_layout< /a> вполне нормально для рисовальных сообществ. Если вам нужно выделить узлы (и их сообщества), я рекомендую вам:

  • выбирать разные цвета для разных сообществ (чем больше цвета отличаются визуально, тем лучше),

  • увеличить размер узлов и

  • сделайте края светло-серыми (так граф выглядит менее загроможденным, а узлы визуально более выделены).

Если вы выберете spring_layout, вы можете дополнительно поэкспериментировать с аргументом k (в документации указано: Увеличьте это значение, чтобы сдвинуть узлы дальше друг от друга). Обратите внимание, что spring_layout может давать разные изображения при каждом запуске кода (таким образом вы можете запускать код несколько раз и сохранять изображение только тогда, когда вы удовлетворены результатом).

В следующем примере я использую граф по умолчанию (nx.karate_club_graph), в котором я автоматически обнаруживаю сообщества с помощью пакета python-louvain (импортированного как community). Размер узла определяется аргументом node_size в nx.draw_networkx_nodes. Цвета узлов зависят от сообщества, к которому они принадлежат — я использую карту цветов plt.cm.RdYlBu (см. дополнительные карты цветов здесь ). Обратите внимание, что вы также можете влиять на размеры узлов (и длины ребер), определяя большее или меньшее изображение с помощью figsize в plt.figure.

import networkx as nx
import community
import matplotlib.pyplot as plt

G = nx.karate_club_graph()  # load a default graph

partition = community.best_partition(G)  # compute communities

pos = nx.spring_layout(G)  # compute graph layout
plt.figure(figsize=(8, 8))  # image is 8 x 8 inches
plt.axis('off')
nx.draw_networkx_nodes(G, pos, node_size=600, cmap=plt.cm.RdYlBu, node_color=list(partition.values()))
nx.draw_networkx_edges(G, pos, alpha=0.3)
plt.show(G)

Вывод (я запускал код несколько раз и выбирал «самое красивое» изображение):

введите описание изображения здесь

Но что, если у вас есть более крупный график с менее очевидными сообществами? Вот более сложный граф со 100 узлами и 100 случайными ребрами (и, следовательно, случайными сообществами), но с тем же подходом к рисованию:

import networkx as nx
import community
import matplotlib.pyplot as plt
import random

H = nx.Graph()

nodes = list(range(100))  # 100 nodes

# add 100 random edges
for i in range(100):
    src = random.choice(nodes)
    dest = random.choice(nodes)
    # we don't want src to be the same as dest
    while src == dest:
        dest = random.choice(nodes)

    H.add_edge(src, dest)

partition = community.best_partition(H)  # compute communities

pos = nx.spring_layout(H)  # compute graph layout
plt.figure(figsize=(10, 10))
plt.axis('off')
nx.draw_networkx_nodes(H, pos, node_size=600, cmap=plt.cm.RdYlBu, node_color=list(partition.values()))
nx.draw_networkx_edges(H, pos, alpha=0.3)
plt.show(H)

Вывод:

введите описание изображения здесь

На изображении выше мы не видим явных сообществ. Здесь у вас есть как минимум три варианта:

  • определить макет графика (координаты/позиции узлов) вручную (pos в моем коде),

  • поэкспериментируйте с различными макетами (см. здесь) и

  • иметь изображение для каждого сообщества (или, по крайней мере, для самых важных сообществ).

Если вы выберете третий вариант, вы можете иметь узлы одного выделенного сообщества больше, чем другие узлы (и, конечно, другого цвета). Вы также можете изменить цвет и толщину краев в этом сообществе (не показано в примере ниже).

node_size = []

# first community against the others
for node, community in partition.items():
    if community == 1:
        node_size.append(900)
    else:
        partition[node] = 0  # I put all the other communities in one communitiy
        node_size.append(300)

plt.figure(figsize=(10, 10))
plt.axis('off')
nodes = nx.draw_networkx_nodes(H, pos, node_size=node_size, cmap=plt.cm.winter, node_color=list(partition.values()))
nx.draw_networkx_edges(H, pos, alpha=0.3)
plt.show(H)

Вывод (выделено только первое сообщество):

введите описание изображения здесь

Если у вас есть несколько изображений для одного и того же графика, я рекомендую, чтобы узлы имели одинаковые позиции на всех из них (вам нужно иметь одинаковые pos между рисунками). Таким образом, изображения более сопоставимы.

person edo    schedule 03.12.2016
comment
Этот подробный ответ действительно полезен. Использование цветовой карты делает код более аккуратным, а график лучше визуализируется. - person user3813057; 05.12.2016