Question: I'm hoping to include a dropdown bar with a callback function that allows the user to display specific points within smaller areas. Initially, I want to use all point geometry data as a default. I'm then aiming to include a dropdown bar and callback function that returns smaller subsets from this main df. This is accomplished by merging the point data within a specific polygon area. Using below, the default df is labelled gdf_all. This contains point data across a large region. The smaller polygon files are subset from gdf_poly. These include African and European continents. These are used within a function to only return point data if it intersects within the polygon shape. I've hard-coded the outputs below. 1) uses gdf_all and 2) uses a subset from African contintent. Ideally, the dropdown bar will be used to input the desired point data to be visualised within the figures. import geopandas as gpd import plotly.express as px import dash from dash import dcc from dash import html import dash_bootstrap_components as dbc # point data gdf_all = gpd.read_file(gpd.datasets.get_path("naturalearth_cities")) # polygon data gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) gdf_poly = gdf_poly.drop('name', axis = 1) gdf_all['LON'] = gdf_all['geometry'].x gdf_all['LAT'] = gdf_all['geometry'].y # subset African continent Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop = True) # subset European continent Eur_gdf_area = gdf_poly[gdf_poly['continent'] == 'Europe'].reset_index(drop = True) # function to merge point data within selected polygon area def merge_withinboundary(gdf1, gdf2): # spatial join data within larger boundary gdf_out = gpd.sjoin(gdf1, gdf2, predicate = 'within', how = 'left').reset_index(drop = True) return gdf_out gdf_Africa = merge_withinboundary(gdf_all, Afr_gdf_area) gdf_Europe = merge_withinboundary(gdf_all, Eur_gdf_area) external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP] app = dash.Dash(__name__, external_stylesheets = external_stylesheets) # function to return selected df for plotting def update_dataset(df): if df == 'gdf_Africa': gdf = gdf_Africa elif df == 'gdf_Europe': gdf = gdf_Europe else: gdf = gdf_all return gdf nav_bar = html.Div([ html.P("area-dropdown:"), dcc.Dropdown( id='data', value='data', options=[{'value': 'gdf_all', 'label': 'gdf_all'}, {'value': 'gdf_Africa', 'label': 'gdf_Africa'}, {'value': 'gdf_Europe', 'label': 'gdf_Europe'} ], clearable=False ), ]) # output 1 df = gdf_all # output 2 #df = gdf_Africa scatter = px.scatter_mapbox(data_frame = df, lat = 'LAT', lon = 'LON', zoom = 2, mapbox_style = 'carto-positron', ) count = df['name'].value_counts() bar = px.bar(x = count.index, y = count.values, color = count.index, ) app.layout = dbc.Container([ dbc.Row([ dbc.Col(html.Div(nav_bar), width=2), dbc.Col([ dbc.Row([ dbc.Col(dcc.Graph(figure = scatter)) ]), dbc.Row([ dbc.Col(dcc.Graph(figure = bar)) ]), ], width=5), dbc.Col([ ], width=5), ]) ], fluid=True) if __name__ == '__main__': app.run_server(debug=True, port = 8051)  Output 1:  Output 2: 

Answer: I think the main task is converting update_dataset into a callback function that takes the dropdown selection as an input, and outputs both the newly updated scatter mapbox and bar chart. In order to do this, you need to provide an id argument in dcc.Graph for both of those figures. Then inside the callback, you can recreate both the scatter mapbox and bar chart depending on the dropdown selection. Also I am not sure about your use case, but for the purpose of this example, I modifed your merge_withinboundary function to perform an inner join instead of a left join (with the sample data you've provided, if you do a left join, you will always end up with gdf_all if that is the first argument to merge_withinboundary – because Afr_gdf_area and Eur_gdf_area are both completely contained inside gdf_all). However, I will leave that decision up to you – perhaps a left join is what you want for your actual data set. For the purpose of this demonstration, I also set zoom = 0 as the default, so when the user selects gdf_all from the dropdown, all of the points are visible. import geopandas as gpd import plotly.express as px import dash from dash import dcc, html, Input, Output import dash_bootstrap_components as dbc # point data gdf_all = gpd.read_file(gpd.datasets.get_path("naturalearth_cities")) # polygon data gdf_poly = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) gdf_poly = gdf_poly.drop('name', axis = 1) gdf_all['LON'] = gdf_all['geometry'].x gdf_all['LAT'] = gdf_all['geometry'].y # subset African continent Afr_gdf_area = gdf_poly[gdf_poly['continent'] == 'Africa'].reset_index(drop = True) # subset European continent Eur_gdf_area = gdf_poly[gdf_poly['continent'] == 'Europe'].reset_index(drop = True) # function to merge point data within selected polygon area def merge_withinboundary(gdf1, gdf2): # spatial join data within larger boundary gdf_out = gpd.sjoin(gdf1, gdf2, predicate = 'within', how = 'inner').reset_index(drop = True) return gdf_out gdf_Africa = merge_withinboundary(gdf_all, Afr_gdf_area) gdf_Europe = merge_withinboundary(gdf_all, Eur_gdf_area) external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP] app = dash.Dash(__name__, external_stylesheets = external_stylesheets) # function to return selected df for plotting @app.callback(Output('scatter-mapbox', 'figure'), Output('bar', 'figure'), Input('data', 'value'), prevent_initial_call=True) # function to return df using smaller areas def update_dataset(dropdown_selection): if dropdown_selection == 'gdf_Africa': gdf = gdf_Africa zoom = 2 elif dropdown_selection == 'gdf_Europe': gdf = gdf_Europe zoom = 2 else: gdf = gdf_all zoom = 0 scatter_subset = px.scatter_mapbox(data_frame = gdf, lat = 'LAT', lon = 'LON', zoom = zoom, mapbox_style = 'carto-positron', ) count = gdf['name'].value_counts() bar_subset = px.bar(x = count.index, y = count.values, color = count.index, ) return scatter_subset, bar_subset nav_bar = html.Div([ html.P("area-dropdown:"), dcc.Dropdown( id='data', value='data', options=[{'value': 'gdf_all', 'label': 'gdf_all'}, {'value': 'gdf_Africa', 'label': 'gdf_Africa'}, {'value': 'gdf_Europe', 'label': 'gdf_Europe'} ], clearable=False ), ]) # output 1 df = gdf_all # output 2 #df = gdf_Africa scatter = px.scatter_mapbox(data_frame = df, lat = 'LAT', lon = 'LON', zoom = 0, mapbox_style = 'carto-positron', ) count = df['name'].value_counts() bar = px.bar(x = count.index, y = count.values, color = count.index, ) app.layout = dbc.Container([ dbc.Row([ dbc.Col(html.Div(nav_bar), width=2), dbc.Col([ dbc.Row([ dbc.Col(dcc.Graph(figure = scatter, id = 'scatter-mapbox')) ]), dbc.Row([ dbc.Col(dcc.Graph(figure = bar, id = 'bar')) ]), ], width=5), dbc.Col([ ], width=5), ]) ], fluid=True) if __name__ == '__main__': app.run_server(debug=True, port = 8051)