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

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

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

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

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

1 ответ

Решение

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

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

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

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

Если вы выбираете 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 между рисунками). Таким образом, изображения более сопоставимы.

Другие вопросы по тегам