Search code examples
pythonplotlychoroplethplotly-express

Plotly Express: Can you manually define legend in px.choropleth?


I am making a px.choropleth() graph in plotly.express.

Here is the code snippet;

import psycopg2
import pandas as pd
import plotly.express as px

''' PostgreSQL Variables '''
# your postgres login variables

''' PostgreSQL Connection '''
# your postgres connection code

''' SQL Query '''
# your SQL Query 

''' Load SQL Queries into Pandas DataFrame '''
African = pd.DataFrame(SQL_Query_Code,
                       columns=['list-of-all-columns'])

''' Variable for Personal Colours '''
# e.g. HTML/HEx code : '#4c5c73'
# List all of the shades/tints codes; in this example I am using the tints codes
my_color_scale = [[0.0, '#4c5c73'], [0.1, '#5D6C81'], [0.2, '#6F7C8F'], [0.3, '#818C9D'], [0.4, '#939DAB'],
                  [0.5, '#A5ADB9'], [0.6, '#B7BDC7'], [0.7, '#C9CED5'], [0.8, '#DBDEE3'], [0.9, '#EDEEF1'],
                  [1.0, '#FFFFFF']]

''' Plotly graph '''
# Government Respond - School Closing
african_figure1 = px.choropleth(African,
                                locations='countrycode',
                                color='c1_school_closing',
                                color_continuous_scale=my_color_scale,
                                range_color=[0, 3],
                                hover_data={'c1_school_closing': False,
                                            'countrycode': False,
                                            'countryname': False},
                                hover_name='countryname',
                                labels={'c1_school_closing': 'SCALE'})

african_figure1.update_layout(geo_scope='africa',
                              coloraxis_reversescale=True, # To reverse the order of color shades/tints
                              title_text='Government Respond - SCHOOL CLOSING <br> '
                                     'Source: <a href="https://www.bsg.ox.ac.uk/research/research-projects'
                                     '/coronavirus-government-response-tracker#data"> Oxford University '
                                     'CORONAVIRUS '
                                     'Government Respond Tracker</a>')

# african_figure1.show()
# african_figure1.write_html('file/path/file_name.html')

This code will create an African map with custom CSS colour that highlighted the number of schools closing in an ordinal scale of the followings;

- 0 'no measures',
- 1 'recommend closing',
- 2 'require closing (only some levels)',
- 3 'require closing all levels', and
- blank 'no data'.

However, when the plotly.express plot this map; the 'blank data' will be omitted automatically. Leaving only the remainders without the text next to it only the numbers in descending order; i.e.

- 3,
- 2,
- 1, and
- 0.

My question for this is;
Is it possible to manually rename the legend automatically created by the px.choropleth?

So, instead of just the numbers; I wanted to have the text definition next to the numbers.
e.g. '3 - require closing all levels'

Thank you in advance.

For your convenience, visual aid in its current state is provided below: plotly-express-image


Solution

  • I'm giving an example. You can use coloraxis_colorbar dictionary in the update layout.

    Here,

    tickvals - enumeration value in the colorbar

    ticktext - text to display against the value

    from urllib.request import urlopen
    import json
    
    
    with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
        counties = json.load(response)
    
    import pandas as pd
    df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
                       dtype={"fips": str})
    
    import plotly.express as px
    
    fig = px.choropleth(df, geojson=counties, locations='fips', color='unemp',
                               color_continuous_scale="Viridis",
                               range_color=(0, 12),
                               scope="usa"
                              )
    fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0},coloraxis_colorbar=dict(
        title="unemployment rate",
        thicknessmode="pixels",
        lenmode="pixels",
        yanchor="top",y=1,
        ticks="outside",
        tickvals=[0,4,8,12],
        ticktext=["Low", "Low Medium", "High Medium", "High"],
        dtick=4
    ))
    fig.show()
    

    enter image description here

    Now coming to your problem,

    Use tickvals=[0,1,2,3] and

    ticktext=['0 - no measures', '1 - recommend closing', '2 - require closing (only some levels)', '3 - require closing all levels']