Gobrel
Gobrel

Reputation: 351

How to use clickable map as a filter for line chart?

I am new to Plotly Dash. I created some Dashboard in Tableau, in Tableau I have a dashboard with a map and a line chart next to it where I can select locations on the map and the line chart shows me the time series line chart from that sensor. I try to do this in Dash and learn some new tools like Dash since I often used Plotly with its beautiful graphs.

I have internal data on a database with some complex logic where I have the locations on a seperate file, since I want to have as less data as possible I don’t want to include lat und lon in the SQL View. For this question I use data available on the web.

I have sensor measuremt data like no2, no, o3 and more from sensors at different locations. My goal ist to have a map with the locations of the sensors. When I click on a location it should show me the line chart and I want to be able to select as many locations as I want so that I can compare the line charts.

Is this possible? I have the line chart, but I can’t connect the part with the map to work. I will use this as a foundation to include many more graphs like bar charts and so on. The top selector will be a dropdown to select the parameter like no2, pm25. Many thanks in advance.

This is the line chart so far:

import plotly.express as px
from jupyter_dash import JupyterDash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import pandas as pd
import dash

# Load Data
df = pd.read_csv('no_data.txt') # file with the measurement data
mp = pd.read_csv('location_sensors.csv') # file with the location data, 3 locations are used in this sample data

# Build App
app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Dropdown(id='dropdown_parameter',
            options=[{'label':x, 'value':x} for x in df['parameter'].unique()],
            value='no2',
            multi=False,
            disabled=False,
            clearable=True,
            searchable=True,
            placeholder='Choose parameter...'
            ),  
    
    html.Div([
        dcc.Graph(id='map_filter'),
        dcc.Graph(id='line_chart')
    ]),
])

@app.callback(
    Output('line_chart', 'figure'),
    Input('dropdown_parameter', 'value'),
)
def update_graph(parameter_chosen):
    dff = df[(df['parameter']==parameter_chosen)]
    fig = px.line(dff, x='date.utc', y='value', color='location')
    return fig

app.run_server(debug=False)

Data: measurement data for line chart: https://github.com/pandas-dev/pandas/blob/master/doc/data/air_quality_long.csv

Location data:

location,latitude,longitude
BETR801,51.20966,4.43182
FR04014,48.83722,2.3939
London Westminster,51.49467,-0.13193

Upvotes: 3

Views: 1405

Answers (1)

emher
emher

Reputation: 6024

If you are not bound to use a Graph component for the map, the Map component from dash-leaflet supports click events natively. Here is a small example, where map clicks are used to update a graph,

import dash_leaflet as dl
import plotly.graph_objs as go
from dash import Dash, dcc, html, Input, Output, State

style = {'width': '50%', 'height': '500px', 'float': 'left'}
# Build small example app.
app = Dash(__name__)
app.layout = html.Div([
    dl.Map(dl.TileLayer(), style=style, id='map'),
    dcc.Graph(id='graph', style=style),
    dcc.Store(id='locations', data=[])
], style={"overflow": "hidden"})

@app.callback(Output('locations', 'data'), Input('map', 'click_lat_lng'),
              State('locations', 'data'), prevent_initial_call=True)
def update_locations(click_lat_lng, locations):
    # Collect location data in a store.
    return locations + [click_lat_lng]

@app.callback(Output('graph', 'figure'), Input('locations', 'data'))
def update_graph(locations):
    # Generate figure based on click data (to simply the example, I just plot lat and lon as bars).
    return go.Figure([go.Bar(x=["Latitude", "Longitude"], y=l) for l in locations])

if __name__ == '__main__':
    app.run_server()

enter image description here

Upvotes: 1

Related Questions