I've got two separate figures that use callbacks to filter spatial coordinates. The figures contain a scatter plot and a heat map. Is it possible to incorporate both within a single figure, but use either a Dropdown
or RadioItems
to select one or the other?
Eventually, the single figure would contain multiple maps to visualise spatial coordinates (scatter, heat map, hex bin, etc.).
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
import numpy as np
data = pd.DataFrame({
'Cat': ['t','y','y','y','f','f','j','k','k','k','s','s','s','s'],
'LAT': [5,6,4,5,4,7,8,9,5,6,18,17,15,16],
'LON': [10,11,9,11,10,8,8,5,8,7,18,16,16,17],
})
N = 30
data = pd.concat([data] * N, ignore_index=True)
data['Color'] = data['Cat'].map(dict(zip(data['Cat'].unique(), px.colors.qualitative.Plotly[:len(data['Cat'].unique())])))
Color = data['Color'].unique()
Type_Category = data['Cat'].unique()
Type_cats = dict(zip(Type_Category, Color))
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filtering = html.Div(children=[
html.Div(children=[
html.Label('Cats', style = {'paddingTop': '2rem', 'display': 'inline-block'}),
dcc.Checklist(
id = 'Cats',
options = [
{'label': 't', 'value': 't'},
{'label': 'y', 'value': 'y'},
{'label': 'f', 'value': 'f'},
{'label': 'j', 'value': 'j'},
{'label': 'k', 'value': 'k'},
{'label': 's', 'value': 's'},
],
value = ['t', 'y', 'f', 'j', 'k', 's'],
),
], className = "two columns",
)
])
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filtering)),
dbc.Col([
dbc.Row([
dbc.Col(dcc.Graph(id = 'scatter-chart')),
]),
]),
dbc.Col(dcc.Graph(id = 'heatmap-chart')),
])
], fluid = True)
df = data
@app.callback(
Output('scatter-chart', 'figure'),
[Input("Cats", "value")])
def scatter_chart(cats):
dff = df[df['Cat'].isin(cats)]
data = px.scatter_mapbox(data_frame = dff,
lat = 'LAT',
lon = 'LON',
color = 'Cat',
color_discrete_map = Type_cats,
zoom = 3,
mapbox_style = 'carto-positron',
)
fig = go.Figure(data = data)
return fig
@app.callback(
Output('heatmap-chart', 'figure'),
[Input("Cats", "value")])
def heatmap_chart(cats):
dff = df[df['Cat'].isin(cats)]
# Creating 2-D grid of features
[X, Y] = np.meshgrid(dff['LAT'], dff['LON'])
Z = np.cos(X / 2) + np.sin(Y / 4)
fig = go.Figure(data =
go.Densitymapbox(lat = dff['LON'],
lon = dff['LAT'],
z = Z,
)
)
fig.update_layout(mapbox_style = "carto-positron")
return fig
if __name__ == '__main__':
app.run_server(debug=True, port = 8051)
As I understand, you can use html.Div
and return dcc.Graph
inside it. Something as below:
import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
import numpy as np
data = pd.DataFrame({
'Cat': ['t','y','y','y','f','f','j','k','k','k','s','s','s','s'],
'LAT': [5,6,4,5,4,7,8,9,5,6,18,17,15,16],
'LON': [10,11,9,11,10,8,8,5,8,7,18,16,16,17],
})
N = 30
data = pd.concat([data] * N, ignore_index=True)
data['Color'] = data['Cat'].map(dict(zip(data['Cat'].unique(), px.colors.qualitative.Plotly[:len(data['Cat'].unique())])))
Color = data['Color'].unique()
Type_Category = data['Cat'].unique()
Type_cats = dict(zip(Type_Category, Color))
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filtering = html.Div(children=[
html.Div(children=[
html.Label('Cats', style = {'paddingTop': '2rem', 'display': 'inline-block'}),
dcc.Checklist(
id = 'Cats',
options = [
{'label': 't', 'value': 't'},
{'label': 'y', 'value': 'y'},
{'label': 'f', 'value': 'f'},
{'label': 'j', 'value': 'j'},
{'label': 'k', 'value': 'k'},
{'label': 's', 'value': 's'},
],
value = ['t', 'y', 'f', 'j', 'k', 's'],
),
],
)
])
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.Div(filtering),
html.Label('Type', style = {'paddingTop': '2rem', 'display': 'inline-block'}),
dcc.RadioItems(['Scatter', 'Heatmaps'], 'Scatter', inline=True,id='maps'),
],width=2),
dbc.Col([
html.Div(id='chart')],width=10)
])
], fluid = True)
df = data
@app.callback(
Output('chart', 'children'),
[Input("Cats", "value"),
Input("maps", "value")])
def scatter_chart(cats,maps):
if maps == 'Scatter':
dff = df[df['Cat'].isin(cats)]
data = px.scatter_mapbox(data_frame = dff,
lat = 'LAT',
lon = 'LON',
color = 'Cat',
color_discrete_map = Type_cats,
zoom = 3,
mapbox_style = 'carto-positron',
)
fig = go.Figure(data = data)
else:
dff = df[df['Cat'].isin(cats)]
# Creating 2-D grid of features
[X, Y] = np.meshgrid(dff['LAT'], dff['LON'])
Z = np.cos(X / 2) + np.sin(Y / 4)
fig = go.Figure(data =
go.Densitymapbox(lat = dff['LON'],
lon = dff['LAT'],
z = Z,
)
)
fig.update_layout(mapbox_style = "carto-positron")
return dcc.Graph(figure=fig)
if __name__ == '__main__':
app.run_server(debug=False, port = 8051)