Построение ориентированных графов в Python таким образом, чтобы показать все ребра отдельно
Я использую Python для имитации процесса, который выполняется на ориентированных графах. Я хотел бы создать анимацию этого процесса.
Проблема, с которой я столкнулся, заключается в том, что большинство библиотек визуализации графиков Python объединяют пары направленных ребер в один край. Например, NetworkX рисует только два ребра при отображении следующего графика, тогда как я хотел бы отображать каждый из четырех ребер отдельно:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.MultiDiGraph()
G.add_edges_from([
(1, 2),
(2, 3),
(3, 2),
(2, 1),
])
plt.figure(figsize=(8,8))
nx.draw(G)
![Output from NetworkX; parallel edges are overlapping, so only two lines are displayed]()
Я хотел бы отобразить что-то вроде этого, каждый отдельный параллельный край:
![Desired output format; parallel edges are drawn separately]()
Вопрос R обратных ребер в igraph в R, похоже, касается одной и той же проблемы, но решение для библиотеки R igraph, а не Python, существует.
Есть ли простой способ создать этот стиль сюжета, используя существующую библиотеку визуализации графиков Python? Это был бы бонус, если он мог поддерживать мультиграфы.
Я открыт для решений, которые вызывают внешнюю программу для создания изображений. Я бы хотел создать целую серию анимационных кадров, поэтому решение должно быть автоматизировано.
Ответы
Ответ 1
В инструментах Graphviz отображаются различные ребра.
Например, давая это:
digraph G {
A -> B;
A -> B;
A -> B;
B -> C;
B -> A;
C -> B;
}
to dot
производит:
![example graph]()
Язык ввода Graphviz довольно прост, поэтому вы можете генерировать его самостоятельно, хотя поиск "python graphviz" вызывает несколько библиотек.
Ответ 2
Использование NetworkX, возможное обходное решение, которое позволяет избежать ввода/вывода файлов и использует dot через pydot для макета:
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from cStringIO import StringIO
g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g) # d is a pydot graph object, dot options can be easily set
# attributes get converted from networkx,
# use set methods to control dot attributes after creation
png_str = d.create_png()
sio = StringIO() # file-like string, appropriate for imread below
sio.write(png_str)
sio.seek(0)
img = mpimg.imread(sio)
imgplot = plt.imshow(img)
для чего требуется seek(0)
, см. Как создать образ из строки в python
Если в консоли IPython (qt), то приведенное выше будет печатать inline и более прямой подход:
import networkx as nx
from IPython.display import Image
g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g)
png_str = d.create_png()
Image(data=png_str)