Choroplethmapbox Streamlit chart not showing solid colors

124 views Asked by At

I am trying to create an interactive chart plotly-Choroplethmapbox.

Ideally I would like a world map, centered on Europe, which could show the outline of all world countries and plot a solid color, using a color scale based on a numeric dataset (e.g. a dataframe column values), and coloring only those countries that are present on such dataset.

I have asked chatgpt to sort this out, and unfortunately for any step forward, it makes two steps back, presenting recurring errors of undefined variable names. What I am pasting here is the latest working example, where unfortunately the colors do not appear.

import streamlit as st
import plotly.graph_objects as go
import pandas as pd
import numpy as np

# Generate random data for countries
np.random.seed(0)
data = {
    'Country': ['United States', 'Canada', 'Mexico', 'Germany', 'France', 'United Kingdom', 'China', 'India', 'Brazil'],
    'Value': np.random.randint(1, 100, 9),
    'lon': [-95.7129, -106.3468, -102.5528, 10.4515, 2.2137, -2.2426, 104.1954, 78.9629, -47.9292],
    'lat': [37.0902, 56.1304, 23.6345, 51.1657, 46.6033, 53.9600, 35.8617, 20.5937, -14.2350]
}

df = pd.DataFrame(data)

# Load GeoJSON data for country boundaries
geojson = 'https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/world-countries.json'

# Streamlit app
st.title('World Countries Map')
st.sidebar.header('Filter Options')

# Select the data variable for coloring the map
color_var = st.sidebar.selectbox('Select Data Variable', df.columns[1:])

# Create a trace for country outlines
trace_outline = go.Choroplethmapbox(
    geojson=geojson,
    locations=df['Country'],
    z=[1] * len(df),  # Assigning a constant value of 1 to show all countries as outlines
    colorscale=[[0, 'rgba(0, 0, 0, 0)']],  # Set the first element of the colorscale to transparent
    marker_opacity=0,
    hoverinfo='skip',
    showscale=False
)

# Create a trace for the colored countries
trace_colored = go.Choroplethmapbox(
    geojson=geojson,
    locations=df['Country'],
    z=df[color_var],
    colorscale=[[0, 'rgba(0, 0, 0, 0)'], [1, 'blue']],  # Set the colorscale to include a solid color
    marker_opacity=0.8,
    marker_line_color='black',
    hovertemplate='<b>%{location}</b><br><br>' +
                  f'{color_var}: %{{z:.2f}}<extra></extra>',
)

# Set up the layout
layout = go.Layout(
    mapbox_style='carto-positron',
    mapbox_zoom=3,  # Adjust the zoom level as needed
    mapbox_center={"lat": 54.5260, "lon": 15.2551},  # Centered on Europe
    margin={"r": 0, "t": 0, "l": 0, "b": 0}
)

# Combine the traces and layout into a figure
fig = go.Figure(data=[trace_outline, trace_colored], layout=layout)

# Add country labels
for country in df['Country']:
    country_row = df[df['Country'] == country]
    lon, lat = country_row['lon'], country_row['lat']
    value = int(country_row[color_var].values[0])
    fig.add_annotation(
        x=float(lon),
        y=float(lat),
        text=str(value),
        showarrow=False,
        font=dict(color='white' if value > 50 else 'black')
    )

# Render the map using Plotly in Streamlit
st.plotly_chart(fig, use_container_width=True)

Here is the previous code that did the job, in a graphically more 'crude' way:

import streamlit as st
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np

# Generate random data for countries
np.random.seed(0)
data = {
    'Country': ['United States', 'Canada', 'Mexico', 'Germany', 'France', 'United Kingdom', 'China', 'India', 'Brazil'],
    'Value': np.random.randint(1, 100, 9)
}

df = pd.DataFrame(data)

# Load GeoJSON data for country boundaries
geojson = 'https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/world-countries.json'

# Streamlit app
st.title('World Countries Map')
st.sidebar.header('Filter Options')

# Select the data variable for coloring the map
color_var = st.sidebar.selectbox('Select Data Variable', df.columns)

# Interactive map with Plotly
fig = px.choropleth(
    df,
    geojson=geojson,
    locations='Country',
    featureidkey='properties.name',
    color=color_var,
    color_continuous_scale='Viridis',
    title='World Countries Map'
)

fig.update_geos(fitbounds='geojson', visible=True)

# Render the map using Plotly in Streamlit
st.plotly_chart(fig, use_container_width=True)
0

There are 0 answers