Black Lives Matter. Please consider donating to Black Girls Code today.

Plotly arrow in scattergeo with text on the line

I have the following code to generate the plot with Plotly in Python 3.7. I am trying to make the line an arrow instead that is pointing to Fort Lauderdale. Also, in the center of the line, I want to have some text. There are many references but no proper answer available.

import numpy as np
import pandas as pd
import plotly.graph_objects as go

np.random.seed(1)
I_list = list(np.random.randint(0,3229,10))
skiplist = set(range(1, 3229)) - set(I_list)
locations = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_us_cities.csv', skiprows=skiplist)

scale = 5000
fig = go.Figure()
fig.add_trace(go.Scattergeo(
        locationmode = 'USA-states',
        lon = locations['lon'],
        lat = locations['lat'],
        text = locations['name'],
        textfont = {"color": 'black',
                    "family":'Times New Roman',
                    "size":14},
        textposition="top center",
        name = "Candidate Facility",
        mode ="markers+text",
        marker = dict(
            size = 10,
            color = "black",
            line_color='black',
            line_width=0.5,
            sizemode = 'area')))

fig.add_trace(go.Scattergeo(
    lat = [locations['lat'][5], locations['lat'][0]],
    lon = [locations['lon'][5], locations['lon'][0]],
    mode = 'lines',
    line = dict(width = 2, color = 'blue'),
))

fig.update_layout(
        showlegend = False,
        geo = dict(
            scope = 'usa',
            landcolor = 'rgb(217, 217, 217)'))
fig.show()

enter image description here

Hi @tcokyasar,

Plotly does not provide an arrow marker but with a few lines of code we get it:

import numpy as np
import pandas as pd
import plotly.graph_objects as go

np.random.seed(1)
I_list = list(np.random.randint(0,3229,10))
skiplist = set(range(1, 3229)) - set(I_list)
locations = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_us_cities.csv', skiprows=skiplist)

scale = 5000
fig = go.Figure()
fig.add_trace(go.Scattergeo(
        locationmode = 'USA-states',
        lon = locations['lon'],
        lat = locations['lat'],
        text = locations['name'],
        textfont = {"color": 'black',
                    "family":'Times New Roman',
                    "size":14},
        textposition="top center",
        name = "Candidate Facility",
        mode ="markers+text",
        marker = dict(
            size = 10,
            color = "black",
            line_color='black',
            line_width=0.5,
            sizemode = 'area')))

fig.add_trace(go.Scattergeo(
    lat = [locations['lat'][5], locations['lat'][0]], 
    lon = [locations['lon'][5], locations['lon'][0]],
    mode = 'lines',
    line = dict(width = 1.5, color = 'blue'),
))

#Workaround to get the arrow at the end of an edge AB

l = 1.1  # the arrow length
widh =0.035  #2*widh is the width of the arrow base as triangle

A = np.array([locations['lon'][5], locations['lat'][5]])
B = np.array([locations['lon'][0], locations['lat'][0]])
v = B-A
w = v/np.linalg.norm(v)     
u  =np.array([-v[1], v[0]])  #u orthogonal on  w
         
P = B-l*w
S = P - widh*u
T = P + widh*u

fig.add_trace(go.Scattergeo(lon = [S[0], T[0], B[0], S[0]], 
                            lat =[S[1], T[1], B[1], S[1]], 
                            mode='lines', 
                            fill='toself', 
                            fillcolor='blue', 
                            line_color='blue'))
#------Display your text at the middle of the segment AB
fig.add_trace(go.Scattergeo(lon =[0.5*(A+B)[0]], lat = [0.5*(A+B)[1]], mode='text', text='               Your text'))

fig.update_layout(width=900, height=750,
        showlegend = False,
        geo = dict(
            scope = 'usa',
            landcolor = 'rgb(217, 217, 217)'))

@empet I really appreciate for this response. I also wonder if there is any way to use self pointing (loop) arrows for some locations, e.g., Hobbs? Should I open a new topic or can you also help me with this problem as well?

@tcokyasar I’ll give the answer here, because it is also a graph edge. But let me try first.