Gerard
Gerard

Reputation: 518

Plotly-Dash: How to create a figure based on two different dataframes?

I am trying to create a graph coming from two separate dataframes in dash. For replicability consider the following:

date = ["2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"]

region = ["Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon"
          ,"Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas"
          ,"Visayas","Visayas"
          ,"Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao"
         ,"Mindanao","Mindanao"
         ,"Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon"
          ,"Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas"
          ,"Visayas","Visayas"
          ,"Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao"
         ,"Mindanao","Mindanao"]
value = ["1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"
        ,"1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"]

product = ["rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
           ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"]
date = [[i] for i in date]
region = [[i] for i in region]
value = [[i] for i in value]
product = [[i] for i in product]

date = pd.DataFrame(date, columns = ["DATE"])
region = pd.DataFrame(region, columns = ["state"])
value = pd.DataFrame(value, columns = ["value"])
product = pd.DataFrame(product, columns = ["product"])
state_level = pd.concat([date,region, value, product], axis=1)

date = ["2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"]
city = ["Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila"
          ,"Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu"
          ,"Metro Cebu","Metro Cebu"
          ,"Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao"
         ,"Metro Davao","Metro Davao"
         ,"Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila"
          ,"Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu"
          ,"Metro Cebu","Metro Cebu"
          ,"Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao"
         ,"Metro Davao","Metro Davao"]

value = ["1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"
        ,"1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"]

product = ["rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
           ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"]
date = [[i] for i in date]
city = [[i] for i in city]
value = [[i] for i in value]
product = [[i] for i in product]

date = pd.DataFrame(date, columns = ["DATE"])
city = pd.DataFrame(city, columns = ["city"])
value = pd.DataFrame(value, columns = ["value"])
product = pd.DataFrame(product, columns = ["product"])
city_level = pd.concat([date,city, value, product], axis=1)

Consider an example graph in plotly:

import plotly.graph_objects as go
historical = state_level[state_level["state"]=="Visayas"]
historical = historical[historical["product"]=="fish"]
historical
fig = go.Figure()
fig.add_trace(go.Scatter(x=historical["DATE"]
                         ,y=historical["value"]
                         ,name="Historical",
                         mode="lines"
                         ,line={"color": "grey", "width": 1}
                         ,showlegend=False))
fig.show()

the graph is: enter image description here

I want to create a dynamic dashboard where the user will choose either at the state level or city level, choose what state or city, and then choose what product (rice or fish), and the graph will just dynamically change based on the user input, my code is as follow:

state = [str(i) for i in state_level.state.unique()]
state.sort(reverse = False)
city = [i for i in city_level.city.unique()]
city.sort(reverse = False)

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

app = JupyterDash(__name__)
all_options = {
    'State': state,
    'City': city
}
app.layout = html.Div([
    dcc.Dropdown(
        id='Level1',
        options=[{'label': k, 'value': k} for k in all_options.keys()],
        value='State'
    ),

    html.Hr(),

    dcc.Dropdown(id='Level2'),
    
    html.Hr(),

    dcc.Dropdown(id='Product',options=[{'label': k, 'value': k} for k in ["rice","fish"]],
                 value='Rice'),
    html.Hr(),

    html.Div(id='display-selected-values')
])


@app.callback(
    Output('Level2', 'options'),
    [Input('Level1', 'value')])

def set_options(selected_level1):
    return [{'label': i, 'value': i} for i in all_options[selected_level1]]
app.run_server(mode='inline')

enter image description here

but I could not figure out how to do this given that my sources are from two different dataframes.

Upvotes: 1

Views: 418

Answers (1)

vestland
vestland

Reputation: 61074

One approach is to store your dataframes in a dictionary like this:

dfs = {'state': state_level,
       'city': city_level}

And then set up a few dynamical callbacks to use as input for a figure like this:

# Make a figure based on the selections
@app.callback( # Columns 2m_temp_prod, or....
    Output('Products_graph', 'figure'),
    [Input('countries-radio', 'value'),
     Input('cities-radio', 'value'),
     Input('products-radio', 'value')])
def make_graph(level, area, product):
    
#     level='city'
#     area='Metro Manila'
#     product = 'fish'
    
    df = dfs[level]
    df = df[df[df.columns[1]]==area]
    df = df[df['product']==product]
    
    fig=go.Figure()
    fig.add_traces(go.Scatter(x=df.DATE, y =df['value'] ))
    return fig

The low variation in your values made it a bit hard to see if the dynamics worked as they shold since you always end up with a straight line. But we can talk details when you find the time to look at the details in the code snippet below. Here's the resulting app:

enter image description here

In this setup, the options for area will change according to city or state level

Complete code:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
import plotly.graph_objects as go

# data
import pandas as pd
date = ["2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"]

region = ["Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon"
          ,"Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas"
          ,"Visayas","Visayas"
          ,"Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao"
         ,"Mindanao","Mindanao"
         ,"Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon","Luzon"
          ,"Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas","Visayas"
          ,"Visayas","Visayas"
          ,"Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao","Mindanao"
         ,"Mindanao","Mindanao"]
value = ["1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"
        ,"1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"]

product = ["rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
           ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"]
date = [[i] for i in date]
region = [[i] for i in region]
value = [[i] for i in value]
product = [[i] for i in product]

date = pd.DataFrame(date, columns = ["DATE"])
region = pd.DataFrame(region, columns = ["state"])
value = pd.DataFrame(value, columns = ["value"])
product = pd.DataFrame(product, columns = ["product"])
state_level = pd.concat([date,region, value, product], axis=1)

date = ["2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"
        ,"2020-01-01","2020-02-01","2020-03-01","2020-04-01","2020-05-01","2020-06-01"
        ,"2020-07-01","2020-08-01","2020-09-01","2020-10-01","2020-11-01","2020-12-01"]
city = ["Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila"
          ,"Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu"
          ,"Metro Cebu","Metro Cebu"
          ,"Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao"
         ,"Metro Davao","Metro Davao"
         ,"Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila","Metro Manila"
          ,"Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu","Metro Cebu"
          ,"Metro Cebu","Metro Cebu"
          ,"Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao","Metro Davao"
         ,"Metro Davao","Metro Davao"]

value = ["1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"
        ,"1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12",
        "1","2","3","4","5","6","7","8","9","10","11","12"]

product = ["rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
           ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice","rice"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"
          ,"fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish","fish"]
date = [[i] for i in date]
city = [[i] for i in city]
value = [[i] for i in value]
product = [[i] for i in product]

date = pd.DataFrame(date, columns = ["DATE"])
city = pd.DataFrame(city, columns = ["city"])
value = pd.DataFrame(value, columns = ["value"])
product = pd.DataFrame(product, columns = ["product"])
city_level = pd.concat([date,city, value, product], axis=1)

# Dash
app = JupyterDash(__name__)
app.config['suppress_callback_exceptions'] = True

dfs = {'state': state_level,
       'city': city_level}


all_options = {
    'state': list(dfs['state']['state'].unique()),
    'city': list(dfs['city']['city'].unique())
}
app.layout = html.Div([
    
    dcc.RadioItems(
        id='countries-radio',
        options=[{'label': k, 'value': k} for k in all_options.keys()],
        value='state'
    ),

    html.Hr(),

    dcc.RadioItems(id='cities-radio'),

    html.Hr(),

  
    
        dcc.RadioItems(
        id='products-radio',
        options=[{'label': k, 'value': k} for k in dfs['state']['product'].unique()],
        value='rice'
    ),
    
    html.Hr(),
    
    html.Div(id='display-selected-values'),
    
    dcc.Graph(id="Products_graph")
    
])


@app.callback(
    Output('cities-radio', 'options'),
    [Input('countries-radio', 'value')])
def set_cities_options(selected_country):
    return [{'label': i, 'value': i} for i in all_options[selected_country]]


@app.callback(
    Output('cities-radio', 'value'),
    [Input('cities-radio', 'options')])
def set_cities_value(available_options):
    return available_options[0]['value']


@app.callback(
    Output('display-selected-values', 'children'),
    [Input('countries-radio', 'value'),
     Input('cities-radio', 'value')])
def set_display_children(selected_country, selected_city):


     return 'Level: ' + u'{} | Area: {}'.format(
#         selected_city, selected_country,
         selected_country, selected_city, 
    )

# Make a figure based on the selections
@app.callback( # Columns 2m_temp_prod, or....
    Output('Products_graph', 'figure'),
    [Input('countries-radio', 'value'),
     Input('cities-radio', 'value'),
     Input('products-radio', 'value')])
def make_graph(level, area, product):
    
#     level='city'
#     area='Metro Manila'
#     product = 'fish'
    
    df = dfs[level]
    df = df[df[df.columns[1]]==area]
    df = df[df['product']==product]
    
    fig=go.Figure()
    fig.add_traces(go.Scatter(x=df.DATE, y =df['value'] ))
    return fig

app.run_server(mode='external', port = 8070, dev_tools_ui=True,
          dev_tools_hot_reload =True, threaded=True)

Upvotes: 1

Related Questions