How to plot lines between all countries with hover text been connected to the lines

I’d like to create a plot which will have lines between all countries. Each line should be able to have its own width and colour. In addition, as I’ll have multiple lines starting from the same point having hover text at the nodes isn’t suitable, I’d like the text to appear when you hover over the line. Is this possible with Plotly?

If so how would you suggest I do it?

Here is a simple example demonstrating that the lines are discontinous and having labels on the nodes isn’t suitable

import plotly.express as px
l1 = [10, 20, None, 10,20,None,50, 60, None]
l2 = [10,20,None, 10,-20,None, 50, 60, None]
names = ['a+','a+',None,'a-','a-',None,'b','b',None]

fig = px.line_mapbox(lat= l1, lon = l2, hover_name=names)
fig.show()

Hi @this_josh welcome to the forums. I don’t know about plotly.express but here is a way to do something like this with plotly.graph_objects. You will have to update the hovertemplate to display what you want it to display.

import plotly.graph_objects as go
import plotly.express as px
import itertools as it
import numpy as np

# generate data
x = np.arange(10)
y = np.arange(10)


# create coordinate  pairs
x_pairs = list(it.pairwise(x))
y_pairs = list(it.pairwise(y))

# create mid points
x_mid = [sum(mid)/2 for mid in x_pairs]
y_mid = [sum(mid)/2 for mid in y_pairs]

# create base figure
fig = go.Figure()

# add traces (line segments)
for x, y, color in zip(x_pairs, y_pairs, px.colors.sequential.deep):
    fig.add_trace(
        go.Scatter(
            x=x,
            y=y, 
            mode='lines', 
            line={'color': color},
            hoverinfo='skip'
        )
    )
# add trace of midpoints for hover information
fig.add_scatter(
    x=x_mid,
    y=y_mid,
    mode='markers',
    marker_color='rgba(0,0,0,0.0)', # set alpha channel to 0.0 --> transparent 
    hovertemplate = "x: %{x} <br> y: %{y} <extra></extra>", # show midpoint coordinates, hide trace name
    hoverlabel = {'bgcolor': px.colors.sequential.deep} 
)    

fig.update_layout(showlegend=False)

newplot (12)
mrep line_color

1 Like

Thank you for your answer.

Typically I prefer graph_objects, but express is more documented when using Mapbox.

Unfortunately, this solution still has labels about a node (you’re adding a node at the halfway point). I’d like to have the label about the line rather than a node as this will be better when there’s a wide variety of line lengths.

I’m also not sure this method scales well to >1000 traces with each having unique attributes, e.g. colour?

I understand the problem.

As for showing hover on the line: there is no such functionality (as far as I know). Maybe just include more points along the line instead of just a mid point.

Concerning scaling: you could try and let us know, would be interesting to know.

1 Like

Thanks, I’m currently doing something like this, so far its running better than I expected, I think because it is a single trace. However, to have each line uniquely style they have to become individual traces which is problematic.

1 Like

By aggregating line styles I’ve been able to reduce the number of traces from #lines to #styles which improves performance enough.

Although the solution does feel like brute force it does approximately work.

TLDR;
Interpolate lots of points along your edges, hover text can snap to them
Aggregate style to reduce their number

1 Like