Я пытаюсь создать линейный сетевой граф, используя Python
(желательно с matplotlib
и networkx
, хотя он будет интересоваться bokeh
), похожим по понятию ниже.
Как этот график графика может быть построен эффективно (pos
?) в Python с помощью networkx
? Я хочу использовать это для более сложных примеров, поэтому я чувствую, что жесткое кодирование позиций для этого простой пример не будет полезен:(. Имеет ли networkx
решение этого?
Я не видел ни одного учебника о том, как это можно достичь в networkx
, поэтому я считаю, что этот вопрос станет надежным ресурсом для сообщества. Я подробно рассмотрел networkx
учебники, и ничего подобного не существует. Макеты для networkx
сделали бы этот тип сети невозможным для интерпретации без тщательного использования аргумента pos
... который, я считаю, является моим единственным вариантом. Ни один из предварительно вычисленных макетов в документации https://networkx.github.io/documentation/networkx-1.9/reference/drawing.html, похоже, хорошо справляется с этим типом структуры сети.
Простой пример:
(A) каждый внешний ключ - это итерация в графе, перемещающемся слева направо (например, итерация 0 представляет образцы, итерация 1 имеет группы 1 - 3, то же самое с итерацией 2, итерация 3 имеет группы 1 - 2 и т.д..). (B) Внутренний словарь содержит текущую группировку на этой конкретной итерации, а веса для слияния предыдущих групп, которые представляют текущую группу (например, iteration 3
имеет Group 1
и Group 2
, а для iteration 4
все iteration 3's
> Group 2
перешел в iteration 4's
Group 2
, но iteration 3's
Group 1
был разделен. Весы всегда суммируются до 1.
Мой код для соединений w/weight для вышеприведенного графика:
D_iter_current_previous = {
1: {
"Group 1":{"sample_0":0.5, "sample_1":0.5, "sample_2":0, "sample_3":0, "sample_4":0},
"Group 2":{"sample_0":0, "sample_1":0, "sample_2":1, "sample_3":0, "sample_4":0},
"Group 3":{"sample_0":0, "sample_1":0, "sample_2":0, "sample_3":0.5, "sample_4":0.5}
},
2: {
"Group 1":{"Group 1":1, "Group 2":0, "Group 3":0},
"Group 2":{"Group 1":0, "Group 2":1, "Group 3":0},
"Group 3":{"Group 1":0, "Group 2":0, "Group 3":1}
},
3: {
"Group 1":{"Group 1":0.25, "Group 2":0, "Group 3":0.75},
"Group 2":{"Group 1":0.25, "Group 2":0.75, "Group 3":0}
},
4: {
"Group 1":{"Group 1":1, "Group 2":0},
"Group 2":{"Group 1":0.25, "Group 2":0.75}
}
}
Это то, что произошло, когда я сделал график в networkx
:
import networkx
import matplotlib.pyplot as plt
# Create Directed Graph
G = nx.DiGraph()
# Iterate through all connections
for iter_n, D_current_previous in D_iter_current_previous.items():
for current_group, D_previous_weights in D_current_previous.items():
for previous_group, weight in D_previous_weights.items():
if weight > 0:
# Define connections using `|__|` as a delimiter for the names
previous_node = "%d|__|%s"%(iter_n - 1, previous_group)
current_node = "%d|__|%s"%(iter_n, current_group)
connection = (previous_node, current_node)
G.add_edge(*connection, weight=weight)
# Draw Graph with labels and width thickness
nx.draw(G, with_labels=True, width=[G[u][v]['weight'] for u,v in G.edges()])
Примечание. Единственный другой способ, который я мог бы сделать, заключался бы в matplotlib
создании графика рассеяния с каждым тиком, представляющим итерацию (5, включая исходные образцы), а затем подключение точек друг к другу с разными весами, Это был бы довольно грязный код, особенно пытающийся выровнять края маркеров с соединениями... Однако я не уверен, что это и networkx
- лучший способ сделать это, или если есть инструмент (например, bokeh
или plotly
), который предназначен для такого типа построения.