pythonplotlyvisualizationplotly-pythonchoropleth

How can I edit the legend of a chloropleth map?


I am working on a map showing the minimum wage across the states in the US.

My code generates a map that looks good, but the legend is unordered, which is awkward. I would like it to be in ascending order (ie $7.25-8, $8-9,...). Along with this, the legend title currently just says "color" and I would like to be able to change this to be more descriptive. How can I do this?

Here is my current code:


import plotly.express as px


fig = px.choropleth(locations=df['state'], 
                    locationmode='USA-states',
                    color=df['wage_cat'],
                    color_discrete_map={ '$7.25-8':'#e0e6f6',
 '$8-9':'#c1ccee',
 '$9-10':'#a2b3e5',
    '$10-11':'#8399dd',
 '$11-12':'#6480d4',
 '$12-13':'#4566cb',
 '$13-14':'#3353b7',
 '$14-15':'#2a4598',
 '$15-16':'#223779',
 '$17-18':'#19295A',
                                       'No state minimum wage':'#f9fafd'}
    )

fig.update_layout(
    title_text='State Minimum Wage as of 1-1-24',
    
    geo = dict(
        scope='usa',
        projection=go.layout.geo.Projection(type = 'albers usa'),
        showlakes=True, # lakes
        lakecolor='rgb(255, 255, 255)'),
)
                   
fig.show()

Solution

  • You can make the wage_cat column a CategoricalDtype (see documentation here), then sort df by wage_cat before passing it to px.choropleth. To update the legend title, you can use the legend_title_text argument in fig.update_layout.

    Something like the following:

    all_wage_categories = ['$7.25-8',
     '$8-9',
     '$9-10',
     '$10-11',
     '$11-12',
     '$12-13',
     '$13-14',
     '$14-15',
     '$15-16',
     '$17-18',
     'No state minimum wage']
    
    df['wage_cat'] = pd.Categorical(df['wage_cat'], 
                          categories=all_wage_categories,
                          ordered=True)
    df = df.sort_values(by=['wage_cat'])
    

    Using some sample data, here is a fully reproducible example:

    import numpy as np
    import pandas as pd
    import plotly.graph_objects as go
    import plotly.express as px
    
    states = [ 'AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'GA',
               'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME',
               'MI', 'MN', 'MO', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM',
               'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'RI', 'SC', 'SD', 'TN', 'TX',
               'UT', 'VA', 'VT', 'WA', 'WI', 'WV', 'WY']
    
    np.random.seed(42)
    all_wage_categories = ['$7.25-8',
     '$8-9',
     '$9-10',
     '$10-11',
     '$11-12',
     '$12-13',
     '$13-14',
     '$14-15',
     '$15-16',
     '$17-18',
     'No state minimum wage']
    
    wages = np.random.choice(all_wage_categories, size=51)
    df = pd.DataFrame({
        'state': states,
        'wage_cat': wages
    })
    
    df['wage_cat'] = pd.Categorical(df['wage_cat'], 
                          categories=all_wage_categories,
                          ordered=True)
    df = df.sort_values(by=['wage_cat'])
    
    fig = px.choropleth(locations=df['state'], 
                        locationmode='USA-states',
                        color=df['wage_cat'],
                        color_discrete_map={ '$7.25-8':'#e0e6f6',
     '$8-9':'#c1ccee',
     '$9-10':'#a2b3e5',
        '$10-11':'#8399dd',
     '$11-12':'#6480d4',
     '$12-13':'#4566cb',
     '$13-14':'#3353b7',
     '$14-15':'#2a4598',
     '$15-16':'#223779',
     '$17-18':'#19295A',
                                           'No state minimum wage':'#f9fafd'}
        )
    
    fig.update_layout(
        title_text='State Minimum Wage as of 1-1-24',
        legend_title_text='Wage Category',
        
        geo = dict(
            scope='usa',
            projection=go.layout.geo.Projection(type = 'albers usa'),
            showlakes=True, # lakes
            lakecolor='rgb(255, 255, 255)'),
    )
                       
    fig.show()
    

    enter image description here