I am working on a presidential elections project that involves filtering a choropleth map. My data is at the county level, and I have a drop down box that allows a user to select a state. The counties are colored by a blue to red continuous color scale representing the lean from democrat to republican. The variable I use for the color scale is the margin between the vote of both parties.
If the margin is positive, the county should be colored a shade of blue. If the margin is negative, the county should colored a shade of red.
However, when I filter to a particular state and all counties in that state voted for one party, the scale finds the lowest margin value and assigns that a color on the blue end of the spectrum even if that county voted more for the Republican.
Is there a way to fix the color scale when filtering so the counties are colored correctly?
Here is some example code:
import pandas as pd
import dash
import os
from urllib.request import urlopen
import json
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.express as px
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],
["Delaware", "New Castle County", 10003, 0.322, 0.663, -75.513210, 39.156876],
["Delaware", "Sussex County", 10005, 0.559, 0.428, -75.513210, 39.156876],
["District of Columbia", "District of Columbia",11001,0.0712,0.913,-77.014468,38.910270],
["Rhode Island", "Bristol County",44001,0.2429,0.7352,-71.41572,41.65665],
["Rhode Island", "Kent County",44003,0.45117,0.5275,-71.41572,41.65665],
["Rhode Island", "Newport County",44005,0.3406,0.6389,-71.41572,41.65665],
["Rhode Island", "Providence County",44007,0.3761,0.605177,-71.41572,41.65665],
["Rhode Island", "Washington County",44009,0.392032,0.5857,-71.41572,41.65665]
]
data = pd.DataFrame(
data,
columns=[
"State",
"County",
"fips_code",
"perc_gop",
"perc_dem",
"lon",
"lat",
],
)
state_choices = data["State"].sort_values().unique()
data['margin_perc'] = data['perc_dem'] - data['perc_gop']
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": "100%", "display": "inline-block", "text-align": "center"},
)
]
)
@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="margin_perc",
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",
"margin_perc":"% Margin"
},
hover_data={
"fips_code": False,
"State": True,
"County": True,
"perc_gop": True,
"perc_dem": True,
},
)
fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})
return fig
app.run_server(host="0.0.0.0", port="8051")
Figured it out --> needed to read documentation more carefully :/
The color_continuous_midpoint argument came in handy. Just calculated the midpoint for the color variable for the entire dataset and used that as the fixed midpoint in the scale.