Plotly – set decimal place in choropleth

Question:

How do you convert number 1.425887B to 1.4 in plotly choropleth ?

data2022 = dict(type = 'choropleth',
            colorscale = 'agsunset',
            reversescale = True,
            locations = df['Country/Territory'],
            locationmode = 'country names',
            z = df['2022 Population'],
            text = df['CCA3'    ],
            marker = dict(line = dict(color = 'rgb(12, 12, 12)', width=1)),
            colorbar = {'title': 'Population'})

layout2022 = dict(title = '<b>World Population 2022<b>',
               geo = dict(showframe = True,
                          showland = True, landcolor = 'rgb(198, 197, 198)',
                          showlakes = True, lakecolor = 'rgb(85, 173, 240)',
                          showrivers = True, rivercolor = 'rgb(173, 216, 230)', 
                          showocean = True, oceancolor = 'rgb(173, 216, 230)',
                          projection = {'type': 'natural earth'}))

choromap2022 = go.Figure(data=[data2022], layout=layout2022) 

choromap2022.update_geos(lataxis_showgrid = True, lonaxis_showgrid = True)

choromap2022.update_layout(height = 600,
                       title_x = 0.5, 
                       title_font_color = 'red',
                       title_font_family = 'Times New Roman',
                       title_font_size = 30,
                       margin=dict(t=80, r=50,  l=50))

iplot(choromap2022)

This is the image of the result I got, I want to convert the population of China from 1.425887B to 1.4B

I try to look up on the plotly document but cannot find anything.

This is the output of df.head().to_dict()

 'CCA3': {0: 'AFG', 1: 'ALB', 2: 'DZA', 3: 'ASM', 4: 'AND'},
 'Country/Territory': {0: 'Afghanistan',
  1: 'Albania',
  2: 'Algeria',
  3: 'American Samoa',
  4: 'Andorra'},
 'Capital': {0: 'Kabul',
  1: 'Tirana',
  2: 'Algiers',
  3: 'Pago Pago',
  4: 'Andorra la Vella'},
 'Continent': {0: 'Asia', 1: 'Europe', 2: 'Africa', 3: 'Oceania', 4: 'Europe'},
 '2022 Population': {0: 41128771, 1: 2842321, 2: 44903225, 3: 44273, 4: 79824},
 '2020 Population': {0: 38972230, 1: 2866849, 2: 43451666, 3: 46189, 4: 77700},
 '2015 Population': {0: 33753499, 1: 2882481, 2: 39543154, 3: 51368, 4: 71746},
 '2010 Population': {0: 28189672, 1: 2913399, 2: 35856344, 3: 54849, 4: 71519},
 '2000 Population': {0: 19542982, 1: 3182021, 2: 30774621, 3: 58230, 4: 66097},
 '1990 Population': {0: 10694796, 1: 3295066, 2: 25518074, 3: 47818, 4: 53569},
 '1980 Population': {0: 12486631, 1: 2941651, 2: 18739378, 3: 32886, 4: 35611},
 '1970 Population': {0: 10752971, 1: 2324731, 2: 13795915, 3: 27075, 4: 19860},
 'Area (km²)': {0: 652230, 1: 28748, 2: 2381741, 3: 199, 4: 468},
 'Density (per km²)': {0: 63.0587,
  1: 98.8702,
  2: 18.8531,
  3: 222.4774,
  4: 170.5641},
 'Growth Rate': {0: 1.0257, 1: 0.9957, 2: 1.0164, 3: 0.9831, 4: 1.01},
 'World Population Percentage': {0: 0.52, 1: 0.04, 2: 0.56, 3: 0.0, 4: 0.0}}```
Asked By: Đạt Dương

||

Answers:

In Plotly, you can use the tickformat attribute to specify how you want to format the numerical tick labels on the colorbar associated with a choropleth map. For example, if you want to convert the number 1.425887B to 1.4 and display it on the colorbar, you can use the following code:

import plotly.graph_objects as go

# Create the choropleth map
fig = go.Figure(data=go.Choropleth(
    locations = ['US', 'CA', 'MX'],
    z = [1.425887, 0.7, 1.2],
    colorscale = 'Reds',
))

# Set the tickformat for the colorbar
fig.update_layout(colorbar = {'tickformat': ',.1f'})

fig.show()

This will format the tick labels on the colorbar to have one decimal place. You can use any valid format string that is compatible with Python’s str.format() method to specify how you want to format the tick labels. For example, '{:,.2f}' will format the tick labels with two decimal places, and '{:,d}' will format the tick labels as integers with commas as thousand separators.

Answered By: Wesley Ferreira

This is trickier than it appears because plotly uses d3-format, but I believe they are using additional metric abbreviations in their formatting to have the default display numbers larger than 1000 in the format 1.425887B.

My original idea was to round to the nearest 2 digits in the hovertemplate with something like:

data2022 = dict(..., hovertemplate = "%{z:.2r}<br>%{text}<extra></extra>")

However, this removes the default metric abbreviation and causes the entire long form decimal to display. The population of China should show up as 1400000000 instead of 1.4B.

So one possible workaround would be to create a new column in your DataFrame called "2022 Population Text" and format the number using a custom function to round and abbreviate your number (credit goes to @rtaft for their function which does exactly that). Then you can pass this column to customdata, and display customdata in your hovertemplate (instead of z).

import pandas as pd
import plotly.graph_objects as go

data =  {'CCA3': {0: 'AFG', 1: 'ALB', 2: 'DZA', 3: 'ASM', 4: 'AND'},
 'Country/Territory': {0: 'Afghanistan',
  1: 'Albania',
  2: 'Algeria',
  3: 'American Samoa',
  4: 'Andorra'},
 'Capital': {0: 'Kabul',
  1: 'Tirana',
  2: 'Algiers',
  3: 'Pago Pago',
  4: 'Andorra la Vella'},
 'Continent': {0: 'Asia', 1: 'Europe', 2: 'Africa', 3: 'Oceania', 4: 'Europe'},
 '2022 Population': {0: 1412000000, 1: 2842321, 2: 44903225, 3: 44273, 4: 79824},
 '2020 Population': {0: 38972230, 1: 2866849, 2: 43451666, 3: 46189, 4: 77700},
 '2015 Population': {0: 33753499, 1: 2882481, 2: 39543154, 3: 51368, 4: 71746},
 '2010 Population': {0: 28189672, 1: 2913399, 2: 35856344, 3: 54849, 4: 71519},
 '2000 Population': {0: 19542982, 1: 3182021, 2: 30774621, 3: 58230, 4: 66097},
 '1990 Population': {0: 10694796, 1: 3295066, 2: 25518074, 3: 47818, 4: 53569},
 '1980 Population': {0: 12486631, 1: 2941651, 2: 18739378, 3: 32886, 4: 35611},
 '1970 Population': {0: 10752971, 1: 2324731, 2: 13795915, 3: 27075, 4: 19860},
 'Area (km²)': {0: 652230, 1: 28748, 2: 2381741, 3: 199, 4: 468},
 'Density (per km²)': {0: 63.0587,
  1: 98.8702,
  2: 18.8531,
  3: 222.4774,
  4: 170.5641},
 'Growth Rate': {0: 1.0257, 1: 0.9957, 2: 1.0164, 3: 0.9831, 4: 1.01},
 'World Population Percentage': {0: 0.52, 1: 0.04, 2: 0.56, 3: 0.0, 4: 0.0}
}

## rounds a number to the specified precision, and adds metrics abbreviations
## i.e. 14230000000 --> 14B
## reference: https://stackoverflow.com/a/45846841/5327068
def human_format(num):
    num = float('{:.2g}'.format(num))
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude])

df = pd.DataFrame(data=data)
df['2022 Population Text'] = df['2022 Population'].apply(lambda x: human_format(x))

data2022 = dict(type = 'choropleth',
            colorscale = 'agsunset',
            reversescale = True,
            locations = df['Country/Territory'],
            locationmode = 'country names',
            z = df['2022 Population'],
            text = df['CCA3'],
            customdata = df['2022 Population Text'],
            marker = dict(line = dict(color = 'rgb(12, 12, 12)', width=1)),
            colorbar = {'title': 'Population'},
            hovertemplate = "%{customdata}<br>%{text}<extra></extra>"
            )

layout2022 = dict(title = '<b>World Population 2022<b>',
               geo = dict(showframe = True,
                          showland = True, landcolor = 'rgb(198, 197, 198)',
                          showlakes = True, lakecolor = 'rgb(85, 173, 240)',
                          showrivers = True, rivercolor = 'rgb(173, 216, 230)', 
                          showocean = True, oceancolor = 'rgb(173, 216, 230)',
                          projection = {'type': 'natural earth'}))

choromap2022 = go.Figure(data=[data2022], layout=layout2022) 

choromap2022.update_geos(lataxis_showgrid = True, lonaxis_showgrid = True)

choromap2022.update_layout(height = 600,
                       title_x = 0.5, 
                       title_font_color = 'red',
                       title_font_family = 'Times New Roman',
                       title_font_size = 30,
                       margin=dict(t=80, r=50,  l=50),
                       )

choromap2022.show()

Note: Since China wasn’t included in your sample data, I changed the population of AFG to 1412000000 to test that the hovertemplate would display it as '1.4B'.

enter image description here

Answered By: Derek O