4

I'm developing a dashboard application using dash/plotly in Python.

I need to build a map with more than 1000 traces. Because of performance issues, I'm trying to use one single Scattergeo object, but, ordinarily, it does not provide a way to plot each "trace" with a different color.

I would like that each trace contains a different color. For markers, each one can have a single color, but using lines is not possible.

The picture below illustrates what I said above.

enter image description here

Is there any workaround that I could use to solve this plotly issue?

I send a reproducible code below.

Thank you in advance.

Reproducible code:

##################################################
# plotly
##################################################

# Source: https://plotly.com/python/lines-on-maps/

import plotly.graph_objects as go

fig = go.Figure()

fig.add_trace(go.Scattergeo(
    lat = [
        40.7127, 51.5072, None,
        30.7127, 41.5072, None,
        20.7127, 31.5072
    ],
    lon = [
        -74.0059, 0.1275, None,
        -64.0059, -10.1275, None,
        -54.0059, -20.1275
    ],
    mode = 'lines',
    line = dict(
        width=4,
        color = 'blue',
        # I would like something like this:
        # color = [
        #     'red',
        #     None,
        #     'yellow',
        #     None,
        #     'green'
        # ],
    ),
))

fig.add_trace(go.Scattergeo(
    lat = [
        40.7127,
        30.7127,
        20.7127
    ],
    lon = [
        -74.0059,
        -64.0059,
        -54.0059,
    ],
    mode = 'markers',
    marker = dict(
        size = 10,
        color = ['red', 'yellow', 'green'],
        line = dict(
            width = 3,
            color = 'rgba(68, 68, 68, 0)'
        ),

    )
))

fig.update_layout(
    title_text = 'Traces',
    showlegend = False,
    geo = dict(
        resolution = 50,
        showland = True,
        showlakes = True,
        landcolor = 'rgb(204, 204, 204)',
        countrycolor = 'rgb(204, 204, 204)',
        lakecolor = 'rgb(255, 255, 255)',
        projection_type = "equirectangular",
        coastlinewidth = 2,
        lataxis = dict(
            range = [0, 70],
            showgrid = True,
            dtick = 10
        ),
        lonaxis = dict(
            range = [-100, 20],
            showgrid = True,
            dtick = 20
        ),
    )
)

##################################################
# dash
##################################################

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()
app.layout = html.Div([
    dcc.Graph(figure=fig)
])

app.run_server(debug=True, use_reloader=True)
rmmariano
  • 896
  • 1
  • 18
  • 32
  • 2
    Does it have to be a plotly graph? Or would solutions using other components, such as dash-leaflet, be usable? – emher Sep 04 '20 at 19:46
  • Your idea is awesome. I've used dash-leaflet and it worked. Thank you. – rmmariano Sep 10 '20 at 19:45
  • 1
    Thanks! I am happy that you like it :) – emher Sep 11 '20 at 12:34
  • @rmmariano I know this question is old, but do you have any update on this? Here is my question: https://community.plotly.com/t/scattermapbox-line-colors-based-on-value/64082 – Papu May 16 '22 at 12:53

1 Answers1

0

You can create a list containing your latitudes, longitudes, and colors. Then loop through the lists, adding your traces one at a time.

import plotly.graph_objects as go

fig = go.Figure()

## create lists containing your information
lat_list = [[40.7127, 51.5072, None],[30.7127, 41.5072, None],[20.7127, 31.5072]]
lon_list = [[-74.0059, 0.1275, None],[-64.0059, -10.1275, None],[-54.0059, -20.1275]]
colors_list = ['red','yellow','green']

for idx in range(len(colors_list)):
    fig.add_trace(go.Scattergeo(
        lat = lat_list[idx],
        lon = lon_list[idx],
        mode = 'lines',
        line = dict(
            width=4,
            color = colors_list[idx],
        ),
    ))

fig.add_trace(go.Scattergeo(
    lat = [
        40.7127,
        30.7127,
        20.7127
    ],
    lon = [
        -74.0059,
        -64.0059,
        -54.0059,
    ],
    mode = 'markers',
    marker = dict(
        size = 10,
        color = ['red', 'yellow', 'green'],
        line = dict(
            width = 3,
            color = 'rgba(68, 68, 68, 0)'
        ),

    )
))

fig.update_layout(
    title_text = 'Traces',
    showlegend = False,
    geo = dict(
        resolution = 50,
        showland = True,
        showlakes = True,
        landcolor = 'rgb(204, 204, 204)',
        countrycolor = 'rgb(204, 204, 204)',
        lakecolor = 'rgb(255, 255, 255)',
        projection_type = "equirectangular",
        coastlinewidth = 2,
        lataxis = dict(
            range = [0, 70],
            showgrid = True,
            dtick = 10
        ),
        lonaxis = dict(
            range = [-100, 20],
            showgrid = True,
            dtick = 20
        ),
    )
)

fig.show()

enter image description here

Derek O
  • 16,770
  • 4
  • 24
  • 43
  • 1
    Thank you for your answer, but using a loop can cause [performance issues](https://plotly.com/python/lines-on-maps/#performance-improvement-put-many-lines-in-the-same-trace), because of that I was looking for a solution that didn't use a loop. – rmmariano Sep 10 '20 at 19:49
  • 1
    Okay, that's a fair point, since you are plotting more than 1000 traces. Thanks for the feedback! – Derek O Sep 10 '20 at 20:17