Choroplethmapbox - text on plot

Is it possible to display text on a choroplethmapbox chart? Something like displaying text labels in the middle of the polygons?

@fmacedo In order to display some information at the visual center of each Polygon or MultiPolygon of a Choroplethmapbox, you
can define a hovertemplate.

To get a description of this attribute, print:

print(help(go.Choroplethmapbox.hovertemplate))

For this Choroplethmapbox https://plot.ly/~empet/15240, for example,
if geojsondata is the dict read from a geojson file, and df is a pandas.DataFrame containing
the geo-id, the name, and an associated value to each state/region in Norway:

import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/empet/Datasets/master/Norway-vals.csv')

with df.columns:
Index(['geo-id', 'geo-name', 'vals'], dtype='object')

then the Chroplethmapbox definition, that on hover displays the state name and the corresponding value is as follows:

choropleth = go.Choroplethmapbox(z=df['vals'],
                            locations = df['geo-id'], 
                            colorscale = bluecart,
                            colorbar = dict(thickness=20, ticklen=3),
                            geojson = geojsdata,
                            text = df['geo-name'],
                            hovertemplate = '<b>State</b>: <b>%{text}</b>'+
                                            '<br><b>Val </b>: %{z}<br>',
                            marker_line_width=0.1, marker_opacity=0.7)

Chroplethmapbox has a fantastic feature: although we don’t give anywhere in its definition
the geographical position of Polygon/MultiPolygon centers, representing states,
the hoverbox is authomatically placed at the their visual centers.

That is indeed a good feature, and I’m well aware of it! Maybe I didn’t explain myself very well, but what I want is to display fixed text on the plot, not on hover. Something like this (but on a Chroplethmapbox chart of course):

labels

I could add another layer with a scattermapbox and display the text there, but I’m assuming there’s an easier way…?

@fmacedo

I succeedded to display text as in your example above, modifying the Chroplethmapbox definition to:

choropleth = go.Choroplethmapbox(z=df['vals'],
                            locations = df['geo-id'], 
                            colorscale = bluecart,
                            colorbar = dict(thickness=20, ticklen=3),
                            below=True,
                            geojson = geojsdata,
                            hoverinfo ='none',        
                            marker_line_width=0.1, marker_opacity=0.7) 

and defining a Scattermapbox having as lon and lat the coordinates of polygon centers ( I extracted these centers after reading the Norway state shapefile):

centers = go.Scattermapbox(
    lat= [60.02, 59.37, 58.87, 60.29, 69.94, 61.45, 60.32, 62.6 , 64.29, 66.91,
                  61.41, 59.98, 59.11, 61.41, 63.12, 59.52, 69.27, 58.48, 59.33],
    lon= [11.17, 11.31,  7.95,  9.09, 25.85, 11.41,  6.28,  7.69, 12.25, 14.75,
                   9.34, 10.74,  6.22,  6.58, 10.38,  8.53, 19.54,  7.18, 10.13],
    marker = {'color': 'white', 'opacity': 0, 'size': 6},
    mode= 'text',
    showlegend= False,
    hoverinfo='skip',
    text=text=[f"Sales<br>{np.random.randint(7, 17)}%" for k in range(19)] 
)

and data = [choropleth, centers].

Hence you have to find the Polygon centers, and set go.Choroplethmapbox.below=True, to ensure that text is displayed above each polygon shape.

@fmacedo Update to the previous message: Please follow this issue https://github.com/plotly/plotly.js/issues/4152 because at the moment the text isn’t rendered as you wanted.

Thanks @empet, that was my plan B. However, I was hopping for a simpler solution, since I do not have the coordinates of the visual centers of the polygons and, for that, I would have to use an algorithm to calculate them (and that’s probably what I’m going to do actually).

Since the hoverbox is already placed in the visual center of the polygons, and therefore the algorithm for that calculation is already in use, one would assume that it might be simple to place text labels in those same positions with the simple activation of an argument…?

Maybe in the future that option will be available.

EDIT: Actually a simple calculation for a “close-enough-visual-center” (not perfect) is as easy as:

centroid = (sum(lon) / len(lon), sum(lat) / len(lat))

where lon and lat are the longitude and latitude, respectively, of the multiple points that define the polygon.

1 Like