If First Graph Not Clicked, 2nd Graph Does Not Load

Hello,

I am working on a project visualizing US elections data. One part of my project shows a county choropleth map that can be changed by choosing a different state from a dropdown box. To the right of this map is the % of the vote both parties earned for each election for any county. This second graph is populated by clicking on the choropleth county map.

The issue I’m having is when I switch states with the dropdown box, the choropleth map updates as expected, but the second graph goes blank and doesn’t populate until I click on the choropleth map again. What I want to happen is to have the second graph populate automatically with the first county’s data alphabetically (data is already sorted) when a new state is selected.

I tried to implement this below, but it doesn’t seem to be working properly.

Can someone please help direct me to the flaw in my code? Any help would be appreciated! Thank you!

Here is a brief snippet of my code:

import pandas as pd
import numpy as np
import dash
import os
from urllib.request import urlopen
import json
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output 
import plotly.express as px
import plotly.graph_objects as go
from flask import Flask, Response

with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

data = [['Delaware','Kent County', 10001,0.467,0.517,-75.513210,39.156876,2012],
          ['Delaware','New Castle County',10003,0.322,0.663,-75.513210,39.156876,2012],
          ['Delaware','Sussex County',10005,0.559,0.428,-75.513210,39.156876,2012],
          ['District of Columbia','District of Columbia',11001,0.0712,0.913,-77.014468,38.910270,2012],
          ['Delaware','Kent County',10001,0.498,0.449,-75.513210,39.156876,2016],
          ['Delaware','New Castle County',10003,0.327,0.623,-75.513210,39.156876,2016],
          ['Delaware','Sussex County',10005,0.591,0.371,-75.513210,39.156876,2016],
          ['District of Columbia','District of Columbia',11001,0.041,0.928,-77.014468,38.910270,2016],
          ['Delaware','Kent County',10001,0.471,0.511,-75.513210,39.156876,2020],
          ['Delaware','New Castle County',10003,0.307,0.678,-75.513210,39.156876,2020],
          ['Delaware','Sussex County',10005,0.550,0.438,-75.513210,39.156876,2020],
          ['District of Columbia','District of Columbia',11001,0.053,0.921,-77.014468,38.910270,2020]]
          

data=pd.DataFrame(data,columns=['State','County','fips_code','perc_gop','perc_dem','lon','lat','year'])       
state_choices = data['State'].sort_values().unique()

app = dash.Dash(__name__,assets_folder=os.path.join(os.curdir,"assets"))
server = app.server
app.layout = html.Div([
                html.Div([
                    dcc.Dropdown(
                        id='dropdown1',
                        options=[{'label': i, 'value': i} for i in state_choices],
                        value=state_choices[0]
                    )
                ],style={'width': '100%','display': 'inline-block','text-align': 'center'}),
                #State Map with County Choropleth
                html.Div([
                    dcc.Graph(id='state_map')
                ],style={'width': '50%','display': 'inline-block','text-align': 'center'}),
                #Party Line % Graph
                html.Div([
                    dcc.Graph(id='party_line_graph')
                ],style={'width': '50%','display': 'inline-block','text-align': 'center'}),
                html.Pre(id='click-data')
            ])

@app.callback(
    Output('state_map','figure'),
    Input('dropdown1','value'))

def update_figure3(state_select):
        new_df = data[data['State']==state_select]

        avg_lat = new_df['lat'].mean()
        avg_lon = new_df['lon'].mean()
        
        fig = px.choropleth_mapbox(new_df, geojson=counties, locations='fips_code', color='perc_gop',
                                color_continuous_scale="balance",
                                mapbox_style="carto-positron",
                                zoom=6, center = {"lat": avg_lat, "lon": avg_lon},
                                opacity=0.5,
                                labels={'State':'State',
                                        'County':'County',
                                        'perc_gop':'% Republican',
                                        'perc_dem':'% Democratic'},
                                hover_data = {
                                    "fips_code":False,
                                    "perc_gop":False,
                                    "State":True,
                                    "County":True,
                                    "perc_gop":True,
                                    "perc_dem":True})
        fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0},
                            coloraxis_showscale=False)            
        return fig

@app.callback(
    Output('party_line_graph','figure'),
    Input('dropdown1','value'),
    Input('state_map','clickData'))

def update_figure4(state_select,click_county_select):
        if click_county_select is not None:
            new_df = data[data['State']==state_select]
            county_id = click_county_select['points'][0]['customdata'][3]
            new_df2 = new_df[new_df['County']==county_id]
        else:
            new_df = data[data['State']==state_select]
            county_id = new_df['County'][0]
            new_df2 = new_df[new_df['County']==county_id]

        fig = go.Figure()
        fig.add_trace(go.Scatter(x=new_df2['year'], y=new_df2['perc_gop'], name='GOP %',
                         line=dict(color='firebrick', width=4)))
        fig.add_trace(go.Scatter(x=new_df2['year'], y=new_df2['perc_dem'], name ='DEM %',
                         line=dict(color='royalblue', width=4)))
        fig.update_layout(height=350,
                          title=f"Results from {county_id}")
        fig.update_layout(
            title={'x':0.5,'xanchor': 'center','yanchor': 'top'},
            yaxis_tickformat = '%'
        )
        return fig

app.run_server(host='0.0.0.0',port='8051')

Hi @plotme1

Thanks for providing a very nice MWE!

You will get a very helpful error message when you add the Dash dev tools

app.run_server(host='0.0.0.0', port='8051', debug=True)

1 Like

Thanks for the response @AnnMarieW!

That was very helpful! I added in the debug=True and was able to see what you screenshotted above - that I have a Key Error. I tried testing out the line in question where I define county_id in the update_figure4 function under the else condition.

I ran the following lines outside the function to see what was coming up if I simulated what was going on inside the function:

Delaware = data[data['State']=="Delaware"]
county_id = Delaware['County'][0]
county_id

This still outputted ‘Kent County’ which is the first county listed in the state-filtered dataset. How should I be changing the county_id line?

Hi @plotme1

You are specifying the index of the dataframe with this syntax:

county_id = Delaware['County'][0]

However, after you sort or filter, the first item may not be the one with the index of 0 – or as in this case, 0 may not exist in the series. You could reset the index after the filter or sort, or if you just want the first item you could try:

county_id = Delaware['County'].iloc[0]
1 Like

Thanks @AnnMarieW! This solution is almost there! Whenever I don’t click on the map, and then switch between states, the line graph updates appropriately. However, if I click on any county even just once, the line graph will go blank on the next dropdown selection.