Choropleth Plotly Graph not appearing on Dash - python

I have a csv file with various states, and their scores for some particular dates. It is being plotted correctly in the VSCode Notebook but when I try to display it on Dash, the default map is appearing but there's no colour coding. I have tried changing the dataset and even the display options but it's still the same. Anyone else facing this?
I am attaching my entire Dash code below for reference
#importing libraries
import dash
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
app = Dash(__name__)
#-- Import and clean data (importing csv into pandas)
df = pd.read_csv("C:\Data Science\Jupyter_Workspace\Twitter_Sentiment\Data\JSONLs\\final_df.csv")
#print(df[:5]) #printing out a sample to verify if it's correct or not
# Importing the GeoJSON File
import geojson
with open("C:\Data Science\Jupyter_Workspace\Twitter_Sentiment\Dash Deployment\states_india.geojson") as f:
india_states = geojson.load(f)
# ------------------------------------------------------------------------------
# App layout
app.layout = html.Div([
html.H1("Sentiment Timeline for Covid-19 in India 2021-22", style={'text-align': 'center'}),
dcc.Dropdown(id="selected_date",
options=[
{"label": "March 20, 2020", "value": 20200320},
{"label": "March 25, 2020", "value": 20200325},
{"label": "March 27, 2020", "value": 20200327},
{"label": "March 30, 2020", "value": 20200330}],
multi=False,
value=20200320,
style={'width': "40%"}
),
html.Div(id='output_container', children=[]),
html.Br(),
dcc.Graph(id='sentiment_map', figure={})
])
# ------------------------------------------------------------------------------
# Connect the Plotly graphs with Dash Components
#app.callback(
[Output(component_id='output_container', component_property='children'),
Output(component_id='sentiment_map', component_property='figure')],
[Input(component_id='selected_date', component_property='value')]
)
def update_graph(date_selected):
print(date_selected)
print(type(date_selected))
container = "The date chosen by user was: {}".format(date_selected)
dff = df.copy()
dff = dff[dff["date"] == date_selected]
# Plotly Express
fig = px.choropleth_mapbox(
data_frame = dff,
locations = 'state',
geojson = india_states,
range_color=(-1, 1),
color = 'vader_score',
mapbox_style = "carto-positron",
color_continuous_scale = px.colors.diverging.RdBu,
color_continuous_midpoint = 0,
center = {'lat': 24, 'lon': 78},
zoom = 2.85,
labels = {'vader_score': 'Sentiment Score'},
title = "Sentiment Map"
)
return container, fig
# --------------------------------
if __name__ == '__main__':
app.run_server(debug=True)

data sourcing
using publicly available geojson for geometry
generating a data frame of sentiment data for dates in dash app
NB state column corresponds to ID in geojson
import requests
import pandas as pd
import numpy as np
import plotly.express as px
# fmt off
india_states = requests.get("https://raw.githubusercontent.com/Subhash9325/GeoJson-Data-of-Indian-States/master/Indian_States").json()
df = pd.DataFrame({"name":['Andaman and Nicobar', 'Andhra Pradesh', 'Arunachal Pradesh',
'Assam', 'Bihar', 'Chandigarh', 'Chhattisgarh',
'Dadra and Nagar Haveli', 'Daman and Diu', 'Delhi', 'Goa',
'Gujarat', 'Haryana', 'Himachal Pradesh', 'Jammu and Kashmir',
'Jharkhand', 'Karnataka', 'Kerala', 'Lakshadweep',
'Madhya Pradesh', 'Maharashtra', 'Manipur', 'Meghalaya', 'Mizoram',
'Nagaland', 'Orissa', 'Puducherry', 'Punjab', 'Rajasthan',
'Sikkim', 'Tamil Nadu', 'Tripura', 'Uttar Pradesh', 'Uttaranchal',
'West Bengal'],
"state":[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35]})
df = pd.concat([df.assign(date=d, vader_score=np.random.uniform(-1,1,len(df))) for d in [20200320, 20200325, 20200327, 20200330]])
# fmt on
dash app
the issue as such was not with dash but creation of Plotly Express figure
the data frame state column needs to link to an id in geonjson
featureidkey="properties.ID_1" https://plotly.com/python/mapbox-county-choropleth/#indexing-by-geojson-properties
# importing libraries
import dash
from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
from jupyter_dash import JupyterDash
# app = Dash(__name__)
app = JupyterDash(__name__)
# ------------------------------------------------------------------------------
# App layout
app.layout = html.Div(
[
html.H1(
"Sentiment Timeline for Covid-19 in India 2021-22",
style={"text-align": "center"},
),
dcc.Dropdown(
id="selected_date",
options=[
{"label": "March 20, 2020", "value": 20200320},
{"label": "March 25, 2020", "value": 20200325},
{"label": "March 27, 2020", "value": 20200327},
{"label": "March 30, 2020", "value": 20200330},
],
multi=False,
value=20200320,
style={"width": "40%"},
),
html.Div(id="output_container", children=[]),
html.Br(),
dcc.Graph(id="sentiment_map", figure={}),
]
)
# ------------------------------------------------------------------------------
# Connect the Plotly graphs with Dash Components
#app.callback(
[
Output(component_id="output_container", component_property="children"),
Output(component_id="sentiment_map", component_property="figure"),
],
[Input(component_id="selected_date", component_property="value")],
)
def update_graph(date_selected):
print(date_selected)
print(type(date_selected))
container = "The date chosen by user was: {}".format(date_selected)
dff = df.copy()
dff = dff[dff["date"] == date_selected]
# Plotly Express
fig = px.choropleth_mapbox(
data_frame=dff,
locations="state",
geojson=india_states,
featureidkey="properties.ID_1",
range_color=(-1, 1),
color="vader_score",
mapbox_style="carto-positron",
color_continuous_scale=px.colors.diverging.RdBu,
color_continuous_midpoint=0,
center={"lat": 24, "lon": 78},
zoom=2.85,
labels={"vader_score": "Sentiment Score"},
title="Sentiment Map",
)
return container, fig
# --------------------------------
if __name__ == "__main__":
# app.run_server(debug=True)
app.run_server(mode="inline")

Related

Dropdown menu isn't searchable with images as labels

Adding images to dropdown labels as described in paragraph Components as Option Labels in
https://dash.plotly.com/dash-core-components/dropdown
makes labels not searchable even though searchable=True is set.
Is there workaround to make labels searchable as usual?
Minimal working code:
import pandas as pd
import plotly
import plotly.express as px
import json
import dash_bootstrap_components as dbc
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
df = pd.read_csv('data_bdo.csv', index_col=0)
temp=[
{
"label": html.Div(
[
html.Img(src="/assets/1.png", height=20),
html.Div("Python", style={'font-size': 15, 'padding-left': 10}),
], style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
),
"value": "Python",
},
{
"label": html.Div(
[
html.Img(src="/assets/2.png", height=20),
html.Div("Julia", style={'font-size': 15, 'padding-left': 10}),
], style={'display': 'flex', 'align-items': 'center', 'justify-content': 'center'}
),
"value": "Julia",
},]
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.DARKLY],update_title = None )
app.layout = html.Div([
html.Div([
dcc.Dropdown(id='my_dropdown',
options=temp,
searchable=True #allow user-searching of dropdown values
)],className='three columns')])
#app.callback(
Output(component_id='the_graph', component_property='figure'),
[Input(component_id='my_dropdown', component_property='value')]
)
def update_bar_chart(my_dropdown):
df = pd.read_csv('data_bdo.csv', index_col=0)
fig = px.bar(df[["name", my_dropdown]].dropna().sort_values(by=my_dropdown,ascending=False),
x="name",
y=my_dropdown,
template = 'plotly_dark',
text=my_dropdown,
labels={my_dropdown:"Amount of "+ str(my_dropdown)}
)
fig.update_traces(textfont_size=13, textposition="outside", cliponaxis=False)
return fig
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
Dropdown with options of the form [{'label': 'Python', 'value': 'Python'}] is searchable though...

Dropdown and Datatable in dash

I have the datepicker component which filters the datatable (top 10 songs on that specific date).Also I would like to have the bar chart which shows the total number of streamed songs of that top 10 songs (10 bars accordingly) preferably with dropdown core component with the options of the titles of songs that where filtered based on the date (the ones that datatable shows). with the below codem, the dropdown component shows all unique song titles thate are in the df but as I already said I want only the ones which will be picked after filtering on date.
Viz: https://imgur.com/a/i2FY83V
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Output, Input
import plotly.express as px
import dash_bootstrap_components as dbc
from datetime import date
import pandas as pd
df = pd.read_csv('bel.csv')
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.LITERA],
meta_tags=[{'name' : 'viewport',
'content': 'width=device-width, initial-scale=1.0' }]
)
# layout
app.layout = dbc.Container([
dbc.Row([
dbc.Col([
html.H1('Top songs in Belgium',className='text-center text-primary,mb-4'),
html.P ('Analyze the Top streamed songs in a month of between March & April',
className='text-center'),
], width= 12)
]),
dbc.Row([
dbc.Col([
dcc.DatePickerSingle(
id = 'my-date-picker-single',
min_date_allowed=date(2022,3,1),
max_date_allowed= date(2022,5,1),
initial_visible_month=date(2022,3,1),
date= date(2022,3,1)
),
dash_table.DataTable(
id ='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": False, "selectable": True, "hideable": True}
if i == "iso_alpha3" or i == "year" or i == "id"
else {"name": i, "id": i, "deletable": False, "selectable": True}
for i in df.loc[0:4,['Rank', 'Title']]
],
data =df.to_dict('records'),
editable= False,
style_as_list_view=True,
style_header={
'backgroundColor': 'white',
'fontWeight': 'bold',
},
style_data={
'whiteSpace': 'normal',
'height':'auto',
'backgroundColor': 'rgb(50, 50, 50)',
'color': 'white'},
),
], width=5),
dbc.Col([
dcc.Dropdown(id='my-dpdn', multi=True,
placeholder="Select a title",
options=[{'label': x, 'value': x}
for x in sorted(df['Title'].unique())]),
dcc.Graph(id='bar-fig', figure={}),
], width ={'size':5})
]),
dbc.Row([
]),
], fluid= True)
def date_string_to_date(date_string):
return pd.to_datetime(date_string, infer_datetime_format=True)
#app.callback(
dash.dependencies.Output('datatable-interactivity', 'data'),
dash.dependencies.Input('my-date-picker-single','date')
)
def update_data (date):
data = df.to_dict('records')
if date:
mask = (date_string_to_date(df['Chart Date']) == date_string_to_date(date))
data= df.loc[mask].head(10).to_dict('records')
return data
# -------------------------------------------------------------------------
if __name__ == '__main__':
app.run_server(debug=True)

Align header in Dash DataTable

I want to align the header to the left in a Dash DataTable. I use the example code from the Dash DataTable documentation. Then I have implemented the style_header dicitionary as suggested in the DataTable reference.
from dash import Dash, dash_table
import pandas as pd
from collections import OrderedDict
data = OrderedDict(
[
("Date", ["2015-01-01", "2015-10-24", "2016-05-10", "2017-01-10", "2018-05-10", "2018-08-15"]),
("Region", ["Montreal", "Toronto", "New York City", "Miami", "San Francisco", "London"]),
("Temperature", [1, -20, 3.512, 4, 10423, -441.2]),
("Humidity", [10, 20, 30, 40, 50, 60]),
("Pressure", [2, 10924, 3912, -10, 3591.2, 15]),
]
)
df = pd.DataFrame(data)
app = Dash(__name__)
app.layout = dash_table.DataTable(
data=df.to_dict('records'),
columns=[{'id': c, 'name': c} for c in df.columns],
style_header={'textAlign': 'left'},
style_cell={'textAlign': 'left'}
)
if __name__ == '__main__':
app.run_server(debug=True)
I would expect the same behaviour as in style_cell, but it has no effect, the columns are left-aligned and the header is right-aligned. I'm not sure, but it occurs to me since I have updated to Dash 2.1.0. How can I align the header to the left?
The behavior seems to be caused by these styles
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner .column-header-name {
margin-left: auto;
}
As a workaround you could add your own styles to overwrite the above
div.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner .column-header-name {
margin-left: unset;
}

Dash Plotly callback inputs (Updates on Page Load)

I'm new to Dash and I'm trying to figure out how to set Callback inputs.
My Dash app has graphs that I want to dynamically update with new data on every page load (or refresh.)
I don't want to do it through user interaction such as dropdown, radio button...
To do so I have created hidden divs as callback inputs, but I'm not sure this is the proper way.
Is there any other approach that would be more suitable (or elegant) in this situation?
Please let me know if there’s something else in my code that needs to be changed.
This is my code:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
import json
import plotly.express as px
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True
data = [['Blue', 30], ['Red ', 20], ['Green', 60]]
df = pd.DataFrame(data, columns=['Color', 'Number'])
data1 = [['A', 10, 88], ['B ', 50, 45], ['C', 25, 120]]
df1 = pd.DataFrame(data1, columns=['Letter', 'Column1', 'Column2'])
def serve_layout():
slayout = html.Div(children=[
html.H1(children='Colors and Letters', style={'text-align': 'center'}),
html.Div([
html.Div(id='input-value', style={'display': 'none'}),
html.Div(id='intermediate-value', style={'display': 'none'}),
]),
html.Div([dcc.Graph(id='graph', style={'width': 1200,
"margin-left": "auto",
"margin-right": "auto",
}),
dcc.Graph(id='graph1', style={'width': 1200,
"margin-left": "auto",
"margin-right": "auto",
})]),
])
return slayout
#app.callback(Output('intermediate-value', 'children'),
[Input('input-value', 'value')])
def clean_data(value):
df_1 = df
df_2 = df1
datasets = {
'df_1': df_1.to_json(orient='split', date_format='iso'),
'df_2': df_2.to_json(orient='split', date_format='iso')
}
return json.dumps(datasets)
#app.callback(
Output('graph', 'figure'),
[Input('intermediate-value', 'children')])
def update_graph(cleaned_data):
datasets = json.loads(cleaned_data)
dff = pd.read_json(datasets['df_1'], orient='split')
fig = go.Figure(data=[go.Bar(x=dff['Color'], y=dff['Number'], text=dff['Number'], textposition='auto')],
layout=go.Layout())
return fig
#app.callback(
Output('graph1', 'figure'),
[Input('intermediate-value', 'children')])
def update_graph(cleaned_data):
datasets = json.loads(cleaned_data)
dff1 = pd.read_json(datasets['df_2'], orient='split')
fig1 = px.line(x=dff1['Letter'], y=dff1['Column1'], color=px.Constant('Column1'),
labels=dict(x='Letter', y='Column1', color='Letter'))
fig1.add_bar(x=dff1['Letter'], y=dff1['Column2'], name='Column2')
return fig1
app.layout = serve_layout
if __name__ == '__main__':
app.run_server(debug=True)
Thanks for any help on this matter.
If you only want to update the plots on page load / refresh, I would advise against any callbacks and instead directly load the figures.
This way, you can leave out all the hidden and intermediate values.
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
import json
import plotly.express as px
import numpy as np
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config['suppress_callback_exceptions'] = True
def refresh_data():
data = [['Blue', 30], ['Red ', np.random.random(1)[0] * 10], ['Green', 60]]
df = pd.DataFrame(data, columns=['Color', 'Number'])
data1 = [['A', 10, 88], ['B ', 50, 45], ['C', 25, 120]]
df1 = pd.DataFrame(data1, columns=['Letter', 'Column1', 'Column2'])
return df, df1
def serve_layout():
plot_style = {'width': 1200,
"margin-left": "auto",
"margin-right": "auto",
}
slayout = html.Div(children=[
html.H1(children='Colors and Letters', style={'text-align': 'center'}),
html.Div(
[dcc.Graph(figure=get_graph(), id='graph', style=plot_style),
dcc.Graph(figure=get_graph1(), id='graph1', style=plot_style)]),
])
return slayout
def get_clean_data():
df_1, df_2 = refresh_data()
datasets = {
'df_1': df_1.to_json(orient='split', date_format='iso'),
'df_2': df_2.to_json(orient='split', date_format='iso')
}
return json.dumps(datasets)
def get_graph():
datasets = json.loads(get_clean_data())
dff = pd.read_json(datasets['df_1'], orient='split')
fig = go.Figure(data=[
go.Bar(x=dff['Color'], y=dff['Number'], text=dff['Number'],
textposition='auto')],
layout=go.Layout())
return fig
def get_graph1():
datasets = json.loads(get_clean_data())
dff1 = pd.read_json(datasets['df_2'], orient='split')
fig1 = px.line(x=dff1['Letter'], y=dff1['Column1'],
color=px.Constant('Column1'),
labels=dict(x='Letter', y='Column1', color='Letter'))
fig1.add_bar(x=dff1['Letter'], y=dff1['Column2'], name='Column2')
return fig1
app.layout = serve_layout
if __name__ == '__main__':
app.run_server(debug=True)

How do I use Dash Loading with Dash Store?

I am writing a simple Dash page. I get data from external APIs etc. and put this in a dcc.Store. The Graphs then pull the data and plot in callbacks. I am trying to implement the dcc.Loading functionality as the pulling of the data can take some time. However I can't figure out how to trigger the Loading for the Graphs when the work is being done by Store.
Below is an example:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import plotly.express as px
import pandas as pd
import time
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Div(children='''
Dash: A web application framework for Python.
'''),
dcc.Dropdown(
id='demo-dropdown',
options=[
{'label': 'New York City', 'value': 'NYC'},
{'label': 'Montreal', 'value': 'MTL'},
{'label': 'San Francisco', 'value': 'SF'}
],
value='NYC'
),
dcc.Loading(
id='loading01',
children=html.Div(id='loading-output')),
# Store certain values
dcc.Store(
id='session',
storage_type='session'),
])
#app.callback(Output('loading-output', 'children'),
[Input('session', 'modified_timestamp')],
[State('session', 'data')])
def loading_graph(ts, store):
if store is None:
raise PreventUpdate
if 'NYC' in store['value']:
v = 1
elif 'SF' in store['value']:
v=2
else:
v=3
return dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4*v, 1*v, 2*v], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
)
#app.callback(Output('session', 'data'),
[Input('demo-dropdown', 'value')],
[State('session', 'data')])
def storing(value, store):
store = store or {}
store['value'] = value
time.sleep(3)
return store
if __name__ == '__main__':
app.run_server(debug=True)
I guess I was hoping for the spinner to be present whilst Store was fetching things.
Thanks in advance for any help or pointers.
If you want to show a loader when the storing callback is called it also needs to have an output to a Loading components' children property.
You can't have duplicate callback outputs, so you could either combine the callbacks into a single callback. Then you could have a single spinner that is active for as long as the combined callback takes to execute.
Or you could have multiple Loading components: One for each callback function:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import time
external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(
children=[
html.H1(children="Hello Dash"),
html.Div(
children="""
Dash: A web application framework for Python.
"""
),
dcc.Dropdown(
id="demo-dropdown",
options=[
{"label": "New York City", "value": "NYC"},
{"label": "Montreal", "value": "MTL"},
{"label": "San Francisco", "value": "SF"},
],
value="NYC",
),
dcc.Loading(id="loading01", children=html.Div(id="loading-output1")),
dcc.Loading(id="loading02", children=html.Div(id="loading-output2")),
# Store certain values
dcc.Store(id="session", storage_type="session"),
]
)
#app.callback(
Output("loading-output2", "children"),
Input("session", "modified_timestamp"),
State("session", "data"),
prevent_initial_call=True,
)
def loading_graph(ts, store):
if store is None:
raise PreventUpdate
if "NYC" in store["value"]:
v = 1
elif "SF" in store["value"]:
v = 2
else:
v = 3
time.sleep(2)
return dcc.Graph(
id="example-graph",
figure={
"data": [
{
"x": [1, 2, 3],
"y": [4 * v, 1 * v, 2 * v],
"type": "bar",
"name": "SF",
},
{"x": [1, 2, 3], "y": [2, 4, 5], "type": "bar", "name": u"Montréal"},
],
"layout": {"title": "Dash Data Visualization"},
},
)
#app.callback(
Output("session", "data"),
Output("loading-output1", "children"),
Input("demo-dropdown", "value"),
State("session", "data"),
)
def storing(value, store):
time.sleep(2)
store = store or {}
store["value"] = value
return store, ""
if __name__ == "__main__":
app.run_server(debug=True)

Categories

Resources