Color for each line in Lines on Mapbox from GeoJSON

Hello,

I plot a GeoJSON file. I use the following code to get the lat, lon and names from the GeoJSON file.

Example from Plotly.com:

import plotly.express as px
import geopandas as gpd
import shapely.geometry
import numpy as np
import wget

# download a zipped shapefile
wget.download("https://plotly.github.io/datasets/ne_50m_rivers_lake_centerlines.zip")

# open a zipped shapefile with the zip:// pseudo-protocol
geo_df = gpd.read_file("zip://ne_50m_rivers_lake_centerlines.zip")

lats = []
lons = []
names = []

for feature, name in zip(geo_df.geometry, geo_df.name):
    if isinstance(feature, shapely.geometry.linestring.LineString):
        linestrings = [feature]
    elif isinstance(feature, shapely.geometry.multilinestring.MultiLineString):
        linestrings = feature.geoms
    else:
        continue
    for linestring in linestrings:
        x, y = linestring.xy
        lats = np.append(lats, y)
        lons = np.append(lons, x)
        names = np.append(names, [name]*len(y))
        lats = np.append(lats, None)
        lons = np.append(lons, None)
        names = np.append(names, None)

Now, instead of:

fig = px.line_mapbox(lat=lats, lon=lons, hover_name=names,
                     mapbox_style="stamen-terrain", zoom=1)
fig.show()

like on Plotly.com I use graph objects like this:

fig = go.Figure(go.Scattermapbox(
    mode = "lines",
    lon = lons,
    lat = lats,
    color='names',
    text=Names
fig.show()

Since I have 20 different lines with their own name. My question now is, how can I get the lines to have seperate colors and have the legend to show me each line? Right now there is one element in the legend and the color of the lines is the same.

Hi dear @Gobrel

I think you can solve the problem using fig.add_scattermapbox. In the following I have shown your example using mentioned function:

import plotly.express as px
import plotly.graph_objects as go

import geopandas as gpd
import shapely.geometry
import numpy as np
import wget

# download a zipped shapefile
wget.download("https://plotly.github.io/datasets/ne_50m_rivers_lake_centerlines.zip")

# open a zipped shapefile with the zip:// pseudo-protocol
geo_df = gpd.read_file("zip://ne_50m_rivers_lake_centerlines.zip")

lats = []
lons = []
names = []

for feature, name in zip(geo_df.geometry, geo_df.name):
    if isinstance(feature, shapely.geometry.linestring.LineString):
        linestrings = [feature]
    elif isinstance(feature, shapely.geometry.multilinestring.MultiLineString):
        linestrings = feature.geoms
    else:
        continue
    for linestring in linestrings:
        x, y = linestring.xy
        lats = np.append(lats, y)
        lons = np.append(lons, x)
        names = np.append(names, [name]*len(y))
        lats = np.append(lats, None)
        lons = np.append(lons, None)
        names = np.append(names, None)
        
fig = go.Figure()

fig.add_scattermapbox(mode = "lines+markers+text",
                      textfont=dict(family='Balto', size=10, color='pink'),
                      lon = lons, lat = lats,
                      line = dict(width=2, color= 'green'),
                      marker=dict(size=5,color='green'),)

fig.update_layout(mapbox=dict(style="stamen-terrain", center=dict(lat=31.3, lon=49),),
                   margin={"r":0,"t":0,"l":0,"b":0})

fig.show()
1 Like

This colors all lines in green. How can I get own color for each line? Fr example if there are 20 lines in the geojson with 20 names I want every line to have a seperate color.

Simply, you can use the add_scattermapbox multiple times and for lines with same colors use this command separately with the color you want!

For example imagine half of data are green and other half are red:

import plotly.express as px
import plotly.graph_objects as go

import geopandas as gpd
import shapely.geometry
import numpy as np
import wget

# download a zipped shapefile
wget.download("https://plotly.github.io/datasets/ne_50m_rivers_lake_centerlines.zip")

# open a zipped shapefile with the zip:// pseudo-protocol
geo_df = gpd.read_file("zip://ne_50m_rivers_lake_centerlines.zip")

lats = []
lons = []
names = []

for feature, name in zip(geo_df.geometry, geo_df.name):
    if isinstance(feature, shapely.geometry.linestring.LineString):
        linestrings = [feature]
    elif isinstance(feature, shapely.geometry.multilinestring.MultiLineString):
        linestrings = feature.geoms
    else:
        continue
    for linestring in linestrings:
        x, y = linestring.xy
        lats = np.append(lats, y)
        lons = np.append(lons, x)
        names = np.append(names, [name]*len(y))
        lats = np.append(lats, None)
        lons = np.append(lons, None)
        names = np.append(names, None)
# print(lats[1])        


lats1=lats[0:int(len((lats))/2+1)]
lats2=lats[int(len((lats))/2):]
lons1=lons[0:int(len((lons))/2+1)]
lons2=lons[int(len((lons))/2):]
# print('\n',lats[1:10])
# print('\n',lons[1:10])

fig = go.Figure()

fig.add_scattermapbox(mode = "lines+markers+text",
                      textfont=dict(family='Balto', size=10, color='pink'),
                      lon = lons1, lat = lats1,
                      line = dict(width=2, color= 'green'),
                      marker=dict(size=5,color='green'),)

fig.add_scattermapbox(mode = "lines+markers+text",
                      textfont=dict(family='Balto', size=10, color='pink'),
                      lon = lons2, lat = lats2,
                      line = dict(width=2, color= 'red'),
                      marker=dict(size=5,color='red'),)

fig.update_layout(mapbox=dict(style="stamen-terrain", center=dict(lat=31.3, lon=49),),
                   margin={"r":0,"t":0,"l":0,"b":0})

fig.show()

and results:

Ok thank you. Do I understand it right, I do need to use 20 scattermapbox add to get each name its own color? Since I have not much experience in python I thought maybe there is a way to use a loop.

Yes and you understood it correctly.

imagine that you have a list of lats and lons lists and also a list of the colors like this:

lons=[lons1,lons2,lons3,...,lons20]
lats=[lats1,lats2,lats3,...,lats20]
colors=['red','green','blue',...,'black']

Attention: each latsi and lonsi are list of values of your data

Now you can use a loop:

for lat,lon,col in zip(lats,lons,colors):
    fig.add_scattermapbox(mode = "lines+markers+text",
                          textfont=dict(family='Balto', size=10, color='pink'),
                          lon = lon, lat = lat,
                          line = dict(width=2, color= col),
                          marker=dict(size=5,color=col),)

Finally, just know that if the response was what you wanted, click on solution tick!