0

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)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jonboy
  • 415
  • 4
  • 14
  • 45

1 Answers1

1

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)

Enter image description here

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hoa tran
  • 1,391
  • 1
  • 5
  • 14