How to add arrowheads to edges between nodes in a directed network diagram?

I want to draw a graphical network using Plotly in Python. Using a similar approach to the examples at https://plot.ly/python/network-graphs/#create-network-graph and https://plot.ly/python/igraph-networkx-comparison/ I have been able to draw my own network of circular nodes connected by edges. But now I want to add an arrowhead to one end of each edge to show which node is the ‘parent’ of another node. How do I do that please?

Intuitively, I was hoping to find an arrowhead attribute on the Line object for Scatter but no such luck:(.

I can see there’s an option to annotate graphs but it seems a lot of work to define annotations for every single edge since those edges already exist and have been drawn.

Here’s my code so far:

import networkx as nx
import plotly.offline
import plotly.graph_objs as go

def createDiGraph():
    # Create a directed graph (digraph) object; i.e., a graph in which the edges
    # have a direction associated with them.
    G = nx.DiGraph()

    # Add nodes:
    nodes = ['A', 'B', 'C', 'D', 'E']
    G.add_nodes_from(nodes)

    # Add edges or links between the nodes:
    edges = [('A','B'), ('B','C'), ('B', 'D'), ('D', 'E')]
    G.add_edges_from(edges)
    return G

g = createDiGraph()

# Get a layout for the nodes according to some algorithm.
# See https://networkx.github.io/documentation/stable/reference/drawing.html#layout
# for alternative algorithms that are available.
# Set random_state (default=None) if you want the layout to be deterministic
# and repeatable.
node_positions = nx.spring_layout(g, random_state=779)

# The nodes will be plotted as a scatter plot of markers with their names
# above each circle:
node_trace = go.Scatter(
    x=[],
    y=[],
    text=[],
    mode='markers+text',
    textposition='top center',
    textfont=dict(
        family='arial',
        size=18,
        color='rgb(0,0,0)'
    ),
    hoverinfo='none',
    marker=go.Marker(
            showscale=False,
            color='rgb(200,0,0)',
            size=25,
            line=go.Line(width=1, color='rgb(0,0,0)')))

for node in node_positions:
    x, y = node_positions[node]
    node_trace['x'].append(x)
    node_trace['y'].append(y)
    node_trace['text'].append(node)

# The edges will be drawn as lines:
edge_trace = go.Scatter(
    x=[],
    y=[],
    line=go.Line(width=1, color='rgb(150,150,150)'),
    hoverinfo='none',
    mode='lines')

for edge in g.edges:
    x0, y0 = node_positions[edge[0]]
    x1, y1 = node_positions[edge[1]]
    edge_trace['x'].extend([x0, x1, None])
    edge_trace['y'].extend([y0, y1, None])

# Create figure:
fig = go.Figure(data = go.Data([edge_trace, node_trace]),
             layout = go.Layout(
                title = 'Sample Network',
                titlefont = dict(size=16),
                showlegend = False,
                hovermode = 'closest',
                margin = dict(b=20,l=5,r=5,t=40),
                xaxis = go.XAxis(showgrid=False, zeroline=False, showticklabels=False),
                yaxis = go.YAxis(showgrid=False, zeroline=False, showticklabels=False)))

plotly.offline.plot(fig)

+1 this question. It’d be awesome to have the ability to show the direction within directed graphs. I’ve seen people do hacks with cones (3D Vector Arrows, https://stackoverflow.com/questions/51410283/how-to-efficiently-create-interactive-directed-network-graphs-with-arrows-on-p) but seems like there could be a more elegant solution out of the box.

1 Like

Hi @MattH,

There’s nothing built in the create directed graph arrows. The annotations approach is probably the most straightforward at the moment. It would be interesting to add a directed graph figure factory to plotly.py, basically as a way to to automate one of the ‘hacks’ for creating arrows. Sort of like the create_streamline figure factory, which just draws arrow heads as separate scatter lines.

Let me know if anyone is interested in working on this!

-Jon

1 Like

Any updates on directed graphs with arrows on edges?