Annotations on plotly Choropleth + choropleth_mapbox + Scattermapbox

Iโ€™m trying to apply annotations on Choropleth map.
Iโ€™ve tried solution proposed in this tread:

But still not able to make it work.

Data:

https://raw.githubusercontent.com/softhints/Pandas-Exercises-Projects/main/data/europe_pop.csv

Code

Code 1 - mixed from the forum

import plotly.express as px
import geopandas as gpd
import plotly.graph_objects as go
import pandas as pd
mapboxt = "xxx"


europe = pd.read_csv('https://raw.githubusercontent.com/softhints/Pandas-Exercises-Projects/main/data/europe_pop.csv')

lats = europe['lat']
lons = europe['lon']
text= europe['values'].astype(str)


fig = px.choropleth_mapbox(europe, geojson=europe.geometry, locations=europe.index, color='values',
                           mapbox_style="carto-positron", 
                           center={"lat": 55, "lon": 15},
                           zoom=1, opacity=0.5, 
                           hover_data={'values': True},
                           width=600, height=600) 

fig = go.Figure(go.Scattermapbox(lat=lats,
                         lon=lons,
                         mode='text+markers',
                         text=text,   
                                                 textfont=dict(
                        family="san serif",
                        size=15,
                        color="green"
                    ),
                         textposition='top center',
                         marker_size=12, marker_color='red'))



fig.update_layout(title_text ='Europe', title_x =0.5, width=1200, height=1200,
                   mapbox = dict(center= dict(lat=52.370216, lon=4.895168),            
                                 accesstoken= mapboxt,
                                 zoom=6,
                                 style="light" 
                               ))



fig.show()

Code 2: choropleth_mapbox + add_annotation


# Plot choropleth map with value labels
fig = px.choropleth_mapbox(europe, geojson=europe.geometry, locations=europe.index, color='values',
                           mapbox_style="carto-positron", 
                           center={"lat": 55, "lon": 15},
                           zoom=2, 
                           opacity=0.5, 
                           hover_data={'values': True},
                           width=1200, height=1200
                          )  

# Add value labels to the map
for idx, row in europe.iterrows():
    fig.add_annotation(
                       x=row['geometry'].centroid.x, 
                       y=row['geometry'].centroid.y, 
                       text=row['name'],
                        showarrow=True, 
                       font=dict(color='black', 
                                 size=10))
    fig.update_annotations(xref="x", yref="y")

# Show plot
fig.show()

Expected Result

I would like to plot something similar to:

https://www.reddit.com/r/MapPorn/comments/12daw36/anger_map_of_europe/

Results

I can not get colors and text annotation on a single map:

Annotations are wrongly placed:

I tried something as below and it worked.

import plotly.express as px
import geopandas as gpd
import plotly.graph_objects as go
import pandas as pd
from urllib.request import urlopen
import json

europe = pd.read_csv('https://raw.githubusercontent.com/softhints/Pandas-Exercises-Projects/main/data/europe_pop.csv')

lats = europe['lat']
lons = europe['lon']
text= europe['values'].astype(str)

with urlopen('https://raw.githubusercontent.com/leakyMirror/map-of-europe/master/GeoJSON/europe.geojson') as response:
    counties = json.load(response)
    
fig = go.Figure()
fig.add_trace(go.Scattermapbox(lat=lats,
                               lon=lons,
                               mode='text+markers',
                               text=text,
                               textfont=dict(
                                   family="san serif",
                                   size=15),
                               textposition='top center',
                               marker_size=12, 
                               marker_color='red'))

fig.add_trace(go.Choroplethmapbox(geojson=counties,
                                  locations=europe['name'],
                                  z=europe['pop_est'],
                                  colorscale="Reds",
                                  featureidkey="properties.NAME",
                                  marker_opacity=0.8,
                                  marker_line_width=0))

fig.update_layout(title_text ='Europe', 
                  title_x =0.5, 
                  width=1200, 
                  height=1200, 
                  mapbox = dict(center= dict(lat=52.370216, lon=4.895168),            
                                 accesstoken= "your_token",
                                 zoom=3,
                                 style="light"
                               )
                 )
fig.show()

2 Likes

Thank you.
It seems to work for me as well.
Iโ€™ll check what I was missing.

P.S. You shared your access token - I guess itโ€™s better to hide it.

1 Like

Thanks, I edited the post

1 Like

Thank you, noted it.

By converting your csv data to geopandas and using them, you can draw maps without using geojson files. There was a comment on my previous post and I posted a different answer even though it was considered resolved.

import pandas as pd
import plotly.graph_objects as go
import geopandas as gpd
from shapely import wkt

url='https://raw.githubusercontent.com/softhints/Pandas-Exercises-Projects/main/data/europe_pop.csv'

df = pd.read_csv(url, index_col=0)
df['geometry'] = df['geometry'].apply(wkt.loads)
europe = gpd.GeoDataFrame(df, crs='epsg:4326')

lats = europe['lat']
lons = europe['lon']
text= europe['values'].astype(str)

mapbox_token = open("mapbox_api_key.txt").read()

fig = go.Figure()

fig.add_trace(go.Scattermapbox(lat=lats,
                               lon=lons,
                               mode='markers+text',
                               text=text,
                               textfont=dict(
                                   family="san serif",
                                   size=15,
                                   color="green"
                               ),
                               textposition='top center',
                               marker_size=8,
                               marker_color='red'
                              ))

fig.add_trace(go.Choroplethmapbox(geojson=europe.__geo_interface__,
                                  locations=europe['iso_a3'],
                                  z=europe['values'],
                                  featureidkey="properties.iso_a3",
                                  zmin=0.0,
                                  zmax=1.0,
                                  marker_opacity=0.5,
                                 )) 

fig.update_layout(height=600,
                  width=1000,
                  mapbox=dict(
                      center={"lat": 55, "lon": 25},
                      accesstoken=mapbox_token,
                      zoom=2,
                      style="light"
))
              
fig.show()

3 Likes

Thanks both.

Iโ€™ve learned new things and was able to solve the issue.

1 Like