Networkx uses graphviz_layout for layout drawing, edge disappeared

30 views Asked by At

When I use python networkx graphviz_layout to draw hierarchical layouts, the corresponding edge disappears in the generated graph when I try to change the weight of the edge.

Below is the specific code and the image:、

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout

if __name__ == '__main__':
    edges_weight = np.array([
        [1, 2, 30], [2, 3, 22], [3, 4, 5.97],
        [4, 5, 5.97], [3, 6, 16.03], [6, 7, 4.03],
        [7, 8, 4.03], [5, 8, 5.97], [8, 9, 9],
        [9, 16, 10], [2, 10, 8], [10, 11, 8],
        [11, 12, 2], [12, 13, 2], [11, 13,  10], [13, 15, 8],
        [15, 16, 20], [6, 17, 12], [17, 18, 12],
        [18, 15, 12], [16, 14, 30]])

    G = nx.DiGraph()

    for u, v, w in edges_weight:
        G.add_edge(u, v, weight=w)
    edge_labels = nx.get_edge_attributes(G, 'weight')
    print(edge_labels)
    shell_pos = graphviz_layout(G, prog='dot')

    print(nx.edges(G))
    print(shell_pos.items())
    print(shell_pos.values())

    plt.figure(figsize=(10, 15))
    nx.draw_networkx_nodes(G, shell_pos, node_color='lightblue', node_size=1200)
    nx.draw_networkx_labels(G, shell_pos)
    nx.draw_networkx_edges(G, shell_pos, node_size=1200, arrowstyle='->', arrowsize=10, width=2)
    nx.draw_networkx_edge_labels(G, shell_pos, edge_labels=edge_labels)
    plt.show()

right draw

The data is now [11, 13, 10] , and the image is displayed normally at this time

If I change part of the data → [11, 13, 9], the corresponding frame disappears. I don’t know what has happened. Can anyone help me? Thank you very much!

wrong draw

I have searched for various information but have not yet found any valid results

I expect to be able to display the edges 11->13 normally

1

There are 1 answers

0
Dylan J. Louie On

I suspect it is an issue where the edges are overlapping with each other and going behind the nodes instead. An alternative suggestion is to manually plot the nodes hierarchically using NetworkX's multipartite_layout() rather than graphviz_layout(). It still has overlapping issues but they are easier to resolve by moving the node orders and subset groupings around.

For Example: Multipartite Layout Version of the Graph

import matplotlib.pyplot as plt
import networkx as nx
import numpy as np

if __name__ == '__main__':
    edges_weight = np.array([
        [1, 2, 30], [2, 3, 22], [3, 4, 5.97],
        [4, 5, 5.97], [3, 6, 16.03], [6, 7, 4.03],
        [7, 8, 4.03], [5, 8, 5.97], [8, 9, 9],
        [9, 16, 10], [2, 10, 8], [10, 11, 8],
        [11, 12, 2], [12, 13, 2], [11, 13,  9], [13, 15, 8],
        [15, 16, 20], [6, 17, 12], [17, 18, 12],
        [18, 15, 12], [16, 14, 30]])

    G = nx.DiGraph()

    edges = []
    weights = []
    node_subset = {}
    for u, v, w in edges_weight:
        if u not in node_subset.keys():
            node_subset[u] = 10
        node_subset[v] = node_subset[u] - 1
        edges.append((u, v))
        weights.append(w)

    # Sort the nodes
    subsets = sorted(list(set(node_subset.values())))
    subsets = {s: [] for s in subsets}

    for subset in subsets.keys():
        for n, s in node_subset.items():
            if s == subset:
                subsets[subset].append(n)
        subsets[subset] = sorted(subsets[subset], reverse=True)

    # Add Nodes to the Graph
    for subset, nodes in subsets.items():
        nodes = [17.0 if x == 12.0 else 12.0 if x == 17.0 else x for x in nodes]
        G.add_nodes_from(nodes, subset=subset)

    # Make a dict of the edge labels
    edge_labels = dict(zip(edges, weights))

    # Draw the nodes with the multipartite layout
    pos = nx.multipartite_layout(G, align='horizontal')
    nx.draw(G, pos, with_labels=True, node_size=1000, font_size=8)

    # Draw the edges 
    nx.draw_networkx_edges(G, pos, edgelist=edges, arrows=True, node_size=1000)

    # Draw the edge labels 
    counter = 0
    for edge, weight in edge_labels.items():
        nx.draw_networkx_edge_labels(G, pos, edge_labels={edge: float(weight)}, font_size=5)

    # Show the plot
    plt.show()