vivek
vivek

Reputation: 40

How to add static text in map using Plotly Choropleth Python

I am plotting a map using plotly express and geojson file.I want to show static values on the individual district. Currently those values are visible on hover, but I want the values to be seen all the time even without hovering on it.

This is my code:

import json
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.io as pio

x = json.load(open("./odisha_disticts.geojson","r"))

user_data = []
for i in range(len(x['features'])):
    d = x['features'][i]['properties']
    d['Females'] = np.random.randint(0,100,1)[0]
    user_data.append(d)
df = pd.DataFrame(user_data)

df.head()
    ID_2    NAME_2  Females
0   16084   Angul   19
1   16085   Baleshwar   45
2   16086   Baragarh    52
3   16087   Bhadrak     81
4   16088   Bolangir    49

fig = px.choropleth(
    df,
    locations="ID_2",
    featureidkey="properties.ID_2",
    geojson=x,
    color="Females"
)
fig.update_geos(fitbounds="locations", visible=False)

px.scatter_geo(
    df,
    geojson=x,
    featureidkey="properties.NAME_2",
    locations="District",
    text = df["District"]
)

fig.show()

The link to required files is HERE

Upvotes: 0

Views: 782

Answers (1)

r-beginners
r-beginners

Reputation: 35205

To annotate on a map, use a graph_object to go.Choroplethmapbox with go.Scattermapbox with textmode. As a preparation before creating the graph, we need the latitude and longitude for the annotation, so we use geopandas to read the geojson file and find the center of geometry. A warning is displayed at this point because the loaded geometry uses an inappropriate geodetic system to calculate the center. If you have a latitude and longitude you wish to use for your annotations use it. There are two caveats in creating the map: first, you will need the free Mapbox API token. Get it here. second, in go.Scattemapbox(), the mode is text + marker, but if you use text only, an error will occur. The reason is unknown.

import geopandas as gpd
import pandas as pd
import plotly.graph_objects as go

# read your data 
data = pd.read_csv('./data.csv', index_col=0)
# read geojson
x = json.load(open("./odisha_disticts.geojson","r"))

gdf = gpd.read_file('./odisha_disticts.geojson')

gdf['centroid'] = gdf['geometry'].centroid
gdf['lon'] = gdf['centroid'].map(lambda p:p.x)
gdf['lat'] = gdf['centroid'].map(lambda p:p.y)
gdf.head()
    ID_2    NAME_2  geometry    centroid    lon     lat
0   16084   Angul   POLYGON ((85.38891 21.17916, 85.31440 21.15510...   POINT (84.90419 20.98316)   84.904186   20.983160
1   16085   Baleshwar   POLYGON ((87.43902 21.76406, 87.47124 21.70760...   POINT (86.90547 21.48738)   86.905470   21.487376
2   16086   Baragarh    POLYGON ((83.79293 21.56323, 83.84026 21.52344...   POINT (83.34884 21.22068)   83.348838   21.220683
3   16087   Bhadrak     POLYGON ((86.82882 21.20137, 86.82379 21.13752...   POINT (86.61598 20.97818)   86.615981   20.978183
4   16088   Bolangir    POLYGON ((83.45259 21.05145, 83.44352 21.01535...   POINT (83.16839 20.58812)   83.168393   20.588121

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

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

fig = go.Figure()

fig.add_trace(go.Scattermapbox(lat=gdf['lat'],
                               lon=gdf['lon'],
                               mode='text+markers',
                               textposition='top center',
                               text = [str(x) for x in data["District"]],
                               textfont=dict(color='blue')
))

fig.add_trace(go.Choroplethmapbox(geojson=x,
                                  locations=data['id'],
                                  z=data['Females'],
                                  featureidkey="properties.ID_2",
                                  colorscale='Reds',
                                  zmin=0,
                                  zmax=data['Females'].max(),
                                  marker_opacity=0.8,
                                  marker_line_width=0
                                 )
             )

fig.update_layout(height=600,
                  mapbox=dict(
                      center={"lat": gdf['lat'].mean(), "lon": gdf['lon'].mean()},
                      accesstoken=mapbox_token,
                      zoom=5.5,
                      style="light"
))

fig.show()

enter image description here

Upvotes: 1

Related Questions