Search code examples
pythonmatplotlibnetworkxedges

How do I curve edges in networkX graph


I had previous asked this question on how to achieve curved edges in networkX. It was working fine with my previous data, but when I updated the data and the code I'm unsure where I'm going wrong. The edges are only curving for certain nodes, and actually adding connections twice. I don't know why it's drawing the edges twice, once in a straight line and once curved. enter image description here

My code:

import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()

G.add_edge("Ted", "May", weight=0.5)
G.add_edge("Ted", "Ray", weight=1)
G.add_edge("Ted", "Chris", weight=1)
G.add_edge("Ted", "Sam", weight=3)
G.add_edge("Ted", "April", weight=1)
G.add_edge("Ted", "Ana", weight=0)


G.add_edge("Ana", "Ryan", weight=1)
G.add_edge("Ana", "Jim", weight=0.5)
G.add_edge("Ana", "Ben", weight=1)


for0 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 0]
for05 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 0.5]
for1 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 1]
for15 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 1.5]
for3 = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] == 3]



pos = nx.circular_layout(G)  # positions for all nodes
ax=plt.gca()

# nodes
sc = nx.draw_networkx_nodes(G, pos, node_size=700)

# edges


nx.draw_networkx_edges(G, pos, edgelist=for0, width=0)
nx.draw_networkx_edges(G, pos, edgelist=for05, width=0.5)

nx.draw_networkx_edges(G, pos, edgelist=for1, width=1)
nx.draw_networkx_edges(G, pos, edgelist=for15, width=1.5)

nx.draw_networkx_edges(G, pos, edgelist=for3, width=3)

for edge in G.edges():
    source, target = edge
    rad = 0.2
    arrowprops=dict(arrowstyle="-",
                    color='blue',
                    connectionstyle=f"arc3,rad={rad}",
                    linestyle= '-',
                    alpha=0.6,)
    ax.annotate("",
                xy=pos[source],
                xytext=pos[target],
                arrowprops=arrowprops
               )

# labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family="sans-serif")


plt.show()

Solution

  • The straight edges come from the nx.draw_networkx_edges() calls. If you remove them, you are left with just the curved edges, but they don't have the specified edge weights. You can update the for loop as below to get the curved edges with edge weights.

    for edge in G.edges():
        source, target = edge
        rad = 0.2
        arrowprops=dict(lw=G.edges[(source,target)]['weight'],
                        arrowstyle="-",
                        color='blue',
                        connectionstyle=f"arc3,rad={rad}",
                        linestyle= '-',
                        alpha=0.6)
        ax.annotate("",
                    xy=pos[source],
                    xytext=pos[target],
                    arrowprops=arrowprops
                   )
    

    The lw parameter sets the line width based on the "weight" edge attribute from the graph. If that's not what you want you can set it to some default value or remove it.

    graph with weighted curved edges