In choropleth how to create outline for country and differentiate that particular countries states

 f=px.choropleth(recipe,locations='state id',geojson=india_states,color='content view')
f.update_geos(fitbounds="locations",visible=False)
f.show()

here in usa selected states has been highlighted other sates remains transparent color
example :


but i geting like this where states has been highlighted accordance with query but those which are not can’t been seen, like the case in usa
query_2
how to get transperent outlay of states of india which are not accordance with query

hi @Amrith
can you please share your code and data so we can replicate your map.

1 Like

hi Adam i am subscribe in ur youtube channel
with help of ur viedo’s i was replicating to try making own dasboard layout

from dash import Dash, html, dcc, Output, Input, dash_table, callback
import dash_bootstrap_components as dbc
import plotly.express as px
import pandas as pd
import numpy as np
import json

app = Dash(__name__, external_stylesheets=[dbc.themes.LUMEN, dbc.icons.FONT_AWESOME])
server = app.server
# geojson
india_states = "https://gist.githubusercontent.com/jbrobst/56c13bbbf9d97d187fea01ca62ea5112/raw/e388c4cae20aa53cb5090210a42ebb9b765c0a36/india_states.geojson"
recipe = pd.read_excel(r'C:\Users\User\data_science/recipe.xlsx')
recipe['Total time(min)'] = recipe['preparation time(min)'] + recipe['cooking time(min)']
print(recipe.head(5))
print(recipe.columns)
app.layout = dbc.Container([
    dbc.Row([
        dbc.Col([
            html.Span([
                html.I(className="fa-solid fa-bowl-rice"),
                " Top 10 Food recipe ",
                html.I(className="fa-solid fa-bowl-rice")], className='h2')
        ], width=10)
    ], justify='center', className='my-2'),

    dbc.Row([
        dbc.Col([html.Label('diet', className='bg-secondary')], width=3),
        dbc.Col([html.Label('Top 10 Food', className='bg-secondary')], width={"size": 4, "offset": 3}),
    ]),
    dbc.Row([
        dbc.Col([
            dcc.Dropdown([diet for diet in sorted(recipe['type of diet'].unique())], multi=True, id='diet_dpdn'),
            html.Label('course of meal', className='bg-secondary'),
            dcc.Dropdown([meal for meal in sorted(recipe['course of meal'].unique())], multi=True,
                         id='course_of_meal_dpdn'),
            html.Label('drop down', className='bg-secondary'),
            dcc.Dropdown(options=[
                {'label': 'topmost', 'value': '0-10'},
                {'label': '2nd topmost', 'value': '11-21'},
                {'label': '3rd topmost', 'value': '22-32'},
                {'label': '4th topmost', 'value': '33-43'},
                {'label': '5th topmost', 'value': '44-54'},
                {'label': '6th topmost', 'value': '55-65'}
            ], multi=False, id='top_ten_dpdn')
        ], width=3),
        dbc.Col([
            dcc.Graph(id='bar', config={'displayModeBar': False})
        ], width=9)
    ]),
    dbc.Row([
        dbc.Col([dcc.Graph(id='line', config={'displayModeBar': False})], width=5),
        dbc.Col([dcc.Graph(id='choro', config={'displayModeBar': False})], width={"size": 5, "offset": 2})
    ])
])


@callback(
    Output('bar', 'figure'),
    Output('line', 'figure'),
    Output('choro', 'figure'),
    Input('diet_dpdn', 'value'),
    Input('course_of_meal_dpdn', 'value'),
    Input('top_ten_dpdn', 'value')
)
def update_graph(diet_v, course_of_meal_v, top_ten_v):
    dff = recipe.copy()
    dff.columns = [column.replace(" ", "_") for column in dff.columns]
    print(type(diet_v))
    if any([diet_v, course_of_meal_v, top_ten_v]):
        if diet_v is not None:
            if len(diet_v) > 0:
                dff = dff.query(f"type_of_diet in {diet_v}")
        if course_of_meal_v is not None:
            if len(course_of_meal_v) > 0:
                dff = dff.query(f"course_of_meal in {course_of_meal_v}")

        if top_ten_v is not None:
            if len(top_ten_v) > 0:
                dff = dff.iloc[int(top_ten_v.split('-')[0]):int(top_ten_v.split('-')[1])]

        dff = dff.reset_index(drop='True').head(10)
        dff = dff.drop_duplicates(subset='name_of_the_dish')
        fig_bar = px.bar(data_frame=dff,
                         x="content_view", y="name_of_the_dish", orientation='h').update_layout(
            margin=dict(l=10, r=10, t=10, b=10), yaxis=dict(autorange="reversed"))
        # dff = dff.reset_index(drop='True').head(10)
        names = [name.split()[0] for name in dff['name_of_the_dish']]
        fig_line_second = px.line(data_frame=dff, x='name_of_the_dish',
                                  y=['preparation_time(min)', 'cooking_time(min)', 'Total_time(min)'],
                                  labels={'value': 'time(min)'}, text='value'
                                  , markers=True).update_layout(
            margin=dict(l=1, r=1, t=1, b=1),
            legend={'x': 0, 'y': 1, 'bgcolor': 'rgba(0, 0, 0, 0)', 'title': None})
        fig_line_second.update_xaxes(tickvals=np.arange(10), ticktext=names)
        fig_line_second.update_traces(textfont_size=10, textposition="bottom right", cliponaxis=False)

        fig_choropleth = px.choropleth(dff, locations='state', geojson=india_states, featureidkey='properties.ST_NM',
                                       locationmode='geojson-id', color='content_view')
        fig_choropleth.update_geos(fitbounds="locations", visible=False)
        fig_choropleth.update_layout(margin=dict(l=1, r=1, t=1, b=1))
        return fig_bar, fig_line_second, fig_choropleth

    if not any([diet_v, course_of_meal_v]):
        dff = dff.reset_index(drop='True').head(10)
        fig_bar = px.bar(data_frame=dff,
                         x="content_view", y="name_of_the_dish", orientation='h').update_layout(
            margin=dict(l=10, r=10, t=10, b=10), yaxis=dict(autorange="reversed"))
        # dff = dff.reset_index(drop='True').head(10)
        names = [name.split()[0] for name in dff['name_of_the_dish']]
        fig_line_second = px.line(data_frame=dff, x='name_of_the_dish',
                                  y=['preparation_time(min)', 'cooking_time(min)', 'Total_time(min)'],
                                  labels={'value': 'time(min)'}, text='value'
                                  , markers=True).update_layout(
            margin=dict(l=1, r=1, t=1, b=1),
            legend={'x': 0, 'y': 1, 'bgcolor': 'rgba(0, 0, 0, 0)', 'title': None})
        fig_line_second.update_xaxes(tickvals=np.arange(10), ticktext=names)
        fig_line_second.update_traces(textfont_size=10, textposition="bottom right", cliponaxis=False)

        fig_choropleth = px.choropleth(dff, locations='state', geojson=india_states, featureidkey='properties.ST_NM',
                                       locationmode='geojson-id', color='content_view')
        fig_choropleth.update_geos(fitbounds="locations", visible=False)
        fig_choropleth.update_layout(margin=dict(l=1, r=1, t=1, b=1))
        return fig_bar, fig_line_second, fig_choropleth
if __name__ == '__main__':
    app.run(debug=True)

[data]
(recipe.xlsx - Google Sheets)

jeo-jason file map i had taken from github

Can any one
help me to resolve this issue

hi @Amrith

The USA choropleth example in the Plotly docs has state outlines that are done for USA and World countries. That’s why they are gray. For you to have the same result in other maps (like India), you will have to get the geojson data for all the India states and you’ll need to color gray the blank states.

@Amrith
For US the base map exhibits the states boundaries, while for any other country there is a workaround to get displayed these boundaries. But unfortunately you cannot remove the boundaries of neighboring countries from the base map.
Here is what I succeeded to get for India states:

import plotly.express as px
import plotly.graph_objects as go
import urllib.request
import json
import pandas as pd
import numpy as np

# the body of this function I posted 2 years ago here:
# http://localhost:8888/notebooks/Documents/AAAATopojson/India-geo-Choropleth.ipynb
def state_boundaries(geojdata):
    pts = []#list of points defining boundaries of polygons, pts has as coordinates the lon and lat
    for  feature in geojdata['features']:
        if feature['geometry']['type'] == 'Polygon':
            pts.extend(feature['geometry']['coordinates'][0])    
            pts.append([None, None])#mark the end of a polygon   
        
        elif feature['geometry']['type'] == 'MultiPolygon':
            for polyg in feature['geometry']['coordinates']:
                pts.extend(polyg[0])
                pts.append([None, None])#end of polygon
        elif feature['geometry']['type'] == 'LineString': 
            points.extend(feature['geometry']['coordinates'])
            points.append([None, None])
        else: pass           
    #else: raise ValueError("geometry type irrelevant for map")
    lons, lats = zip(*pts) 
    return lons, lats

url ="https://raw.githubusercontent.com/Subhash9325/GeoJson-Data-of-Indian-States/master/Indian_States"
with urllib.request.urlopen(url) as url:
    geojson = json.loads(url.read().decode())
    #print(geojson.keys())
df = pd.DataFrame({"ids": np.arange(1, 36), "vals": np.random.randint(25,35, size=35)})
df1=df[df["vals"]>30]  #Choropleth displays only states with vals >30

lons, lats = state_boundaries(geojson)

fig= go.Figure(go.Scattergeo(lon=lons, lat=lats, mode="lines", line_width=1.5, line_color="white"))

fig.update_layout(width=700, height=750,
        geo = dict(
            scope = 'asia',
            resolution = 110,  #for info help(go.layout.Geo.resolution)
            lonaxis_range= [67, 98 ],
            lataxis_range= [2, 38],
            landcolor = 'rgb(225, 225, 225)',
        ))
#fig.show()   
#define a reduced geojson file to avoid passing non-necessary data to choropleth
reduced_geojson={"type": "FeatureCollection", "features":[]} 

for feat in geojson["features"]:
    if feat["properties"]["ID_1"] in df1["ids"]:
        reduced_geojson["features"].append(feat)
figc = px.choropleth(df1, geojson=reduced_geojson, locations='ids', 
                              color="vals", color_continuous_scale="viridis",
                              featureidkey="properties.ID_1")
#fig1.update_traces(marker_line_color="black", marker_line_width=3) #color and width of boundary color for states displayed by coropleth
fig.add_trace(figc.data[0])
fig.show()

Notice that the resolution of the base map is not the same as the resolution from fig.layout.geoThat’s why parts of the Pakistan boundary is still visible, as well as the boundaries of eastern India neighbouring countries.

1 Like

@empet Thanks for ur response i will try this out