Set specific colour map to Bar-chart with callback - dash Plotly - python

I've got an interactive bar chart that displays counts from days of the week. I'm trying to set the color map so each day of the week maintains the same color. At the moment, if I remove any days, the color changes.
Separately, is it possible to keep the same dropdown values for days of the week and map the same color sequence but plot DATES instead of days of the week?
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
import dash
from dash.dependencies import Input, Output, State
from datetime import datetime
import plotly.graph_objs as go
import plotly.express as px
import pandas as pd
import numpy as np
from datetime import datetime as dt
df = pd.DataFrame({
'Type': ['A','B','B','B','C','C','D','E','E','E','E','F','F','F'],
})
N = 30
df = pd.concat([df] * N, ignore_index=True)
df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst = True).sort_values()
df['TIMESTAMP'] = df['TIMESTAMP'].dt.floor('1min')
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'])
df['YEAR'] = df['DATE'].dt.year
df = df.sort_values(by = 'DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filter_box = html.Div(children=[
################### Filter box ######################
html.Div(children=[
html.Label('Day of the week:', style={'paddingTop': '2rem'}),
dcc.Dropdown(
id='DOW',
options=[
{'label': x, 'value': x} for x in df['DOW'].unique()
],
value=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday'],
multi=True
),
], className="four columns",
style={'padding':'2rem', 'margin':'1rem'} )
])
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(),
]),
dbc.Row([
dbc.Col(dcc.Graph(id = 'date-bar-chart'), style={
"padding-bottom": "10px",
},),
]),
dbc.Row([
]),
], width=5),
dbc.Col([
dbc.Row([
dbc.Col(),
]),
], width=5),
])
], fluid=True)
#app.callback(
Output('date-bar-chart', 'figure'),
[Input("DOW", "value"),
])
def date_chart(dow):
dff = df[df['DOW'].isin(dow)]
count = dff['DOW'].value_counts()
dff['Color'] = dff['DOW'].map(dict(zip(dff['DOW'].unique(),
px.colors.qualitative.Plotly[:len(dff['DOW'].unique())])))
Color = dff['Color'].unique()
Category = dff['DOW'].unique()
cats = dict(zip(Color, Category))
data = px.bar(x = count.index,
y = count.values,
color = count.index,
color_discrete_map = cats,
)
layout = go.Layout(title = 'Date')
fig = go.Figure(data = data, layout = layout)
return fig
if __name__ == '__main__':
app.run_server(debug=True, port = 8051)

The accepted answer is too complicated and doesn't answer the second question.
For the first question on the color_discrete_map parameter, you should define a proper dictionary with keys as week day names and values as colors like this. You don't need df['Color'], Color, Category, etc.
import pandas as pd
...
color_map = {
pd.Timestamp(2023, 2, 13+i).day_name(): # 2-13 was monday.
px.colors.qualitative.Plotly[i]
for i in range(7)
}
...
def date_chart(dow):
dff = df[df['DOW'].isin(dow)]
count = dff['DOW'].value_counts()
data = px.bar(x = count.index,
y = count.values,
color = count.index,
color_discrete_map = color_map,
)
...
For the second question, you need a logic to choose one of the rows matching a given week day. The following is one example which chooses the first one.(This uses the group_by(), so the value_counts() is not necessary.)
def date_chart(dow):
dff = df[df['DOW'].isin(dow)]
g = dff.groupby('DOW', as_index=False)
g_df = g.head(1).merge(g.size())
data = px.bar(x = g_df['DATE'],
y = g_df['size'],
color = g_df['DOW'],
color_discrete_map = color_map,
)
...

Because you are setting cats in your callback so each time your dff change based on filter, your dict will be changed. So that I think you should define your color_discrete_map with df, not dff. And I think you should change your cats to cats = dict(zip(Category,Color))
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
import dash
from dash.dependencies import Input, Output, State
from datetime import datetime
import plotly.graph_objs as go
import plotly.express as px
import pandas as pd
import numpy as np
from datetime import datetime as dt
df = pd.DataFrame({
'Type': ['A','B','B','B','C','C','D','E','E','E','E','F','F','F'],
})
N = 30
df = pd.concat([df] * N, ignore_index=True)
df['TIMESTAMP'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'], dayfirst = True).sort_values()
df['TIMESTAMP'] = df['TIMESTAMP'].dt.floor('1min')
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['TIMESTAMP']])
df['DATE'] = pd.to_datetime(df['DATE'])
df['YEAR'] = df['DATE'].dt.year
df = df.sort_values(by = 'DATE')
df['DOW'] = df['DATE'].dt.weekday
df = df.sort_values('DOW').reset_index(drop=True)
df['DOW'] = df['DATE'].dt.day_name()
df['Color'] = df['DOW'].map(dict(zip(df['DOW'].unique(),
px.colors.qualitative.Plotly[:len(df['DOW'].unique())])))
Color = df['Color'].unique()
Category = df['DOW'].unique()
cats = dict(zip(Category,Color))
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
filter_box = html.Div(children=[
################### Filter box ######################
html.Div(children=[
html.Label('Day of the week:', style={'paddingTop': '2rem'}),
dcc.Dropdown(
id='DOW',
options=[
{'label': x, 'value': x} for x in df['DOW'].unique()
],
value=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday'],
multi=True
),
], className="four columns",
style={'padding':'2rem', 'margin':'1rem'} )
])
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(filter_box, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(),
]),
dbc.Row([
dbc.Col(dcc.Graph(id = 'date-bar-chart'), style={
"padding-bottom": "10px",
},),
]),
dbc.Row([
]),
], width=5),
dbc.Col([
dbc.Row([
dbc.Col(),
]),
], width=5),
])
], fluid=True)
#app.callback(
Output('date-bar-chart', 'figure'),
[Input("DOW", "value"),
])
def date_chart(dow):
dff = df[df['DOW'].isin(dow)]
count = dff['DOW'].value_counts()
data = px.bar(x = count.index,
y = count.values,
color = count.index,
color_discrete_map = cats,
)
return data
if __name__ == '__main__':
app.run_server(debug=False, port = 8051)

Related

Callback error with barchart - Plotly dash

I'm trying to insert an interactive bar-chart using values in a df. Using below, I've got the unique values from Type displayed as RadioItems. I'm aiming to link these to a bar chart within the dbc.Container. The first 5 rows of the df are displayed below. I'm hoping to group each unique value of Type as a total count to be displayed as a bar chart.
Ideally, I'd like to be able to add/remove as many unique values to bar chart through the RadioItems.
Eventually, I'd like to add a date slide where I can select
Type time DATE TIME
0 A 2022-01-01 07:30:00 2022-01-01 07:30:00
1 B 2022-01-01 23:01:00 2022-01-01 23:01:00
2 A 2022-01-01 21:28:00 2022-01-01 21:28:00
3 E 2022-01-01 18:21:00 2022-01-01 18:21:00
4 E 2022-01-01 16:48:00 2022-01-01 16:48:00
current code:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objs as go
import dash
from dash import dcc
from dash import html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
df = pd.DataFrame({
'Type': ['A','B','B','C','D','D','E','E','F']
})
N = 50
df = pd.concat([df] * N, ignore_index=True)
df['time'] = pd.date_range(start='2022/01/01 07:30', end='2022/01/30 08:30', periods=len(df))
df['time'] = pd.to_datetime(df['time'], dayfirst = True).sort_values()
df['time'] = df['time'].dt.floor('1min')
df['DATE'], df['TIME'] = zip(*[(d.date(), d.time()) for d in df['time']])
df['DATE'] = pd.to_datetime(df['DATE'])
df = df.sort_values(by = 'DATE')
date_count = df.groupby(['DATE']).size().reset_index(name = 'Count').sort_values('Count', ascending = False)
date_count["DOW"] = date_count["DATE"].dt.weekday
date_count = date_count.sort_values("DOW").reset_index(drop=True)
date_count["DOW"] = date_count["DATE"].dt.day_name()
external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
radio_items = html.Div([
html.P("Type"),
dcc.RadioItems(
id='Type',
value='Type',
options=[{'value': x, 'label': x}
for x in ['A', 'B', 'C', 'D', 'E', 'F']],
),
])
vess_date_barfig = px.bar(data_frame = date_count,
x = 'DATE',
y = 'Count',
color = 'DOW',
opacity = 0.5,
title = 'Total Daily Count of Type'
)
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.Div(radio_items, className="bg-secondary h-100"), width=2),
dbc.Col([
dbc.Row([
dbc.Col(),
]),
dbc.Row([
dbc.Col(dcc.Graph(figure = vess_date_barfig), style={
"padding-bottom": "10px",
}),
]),
dbc.Row([
dbc.Col(dcc.Graph(id = 'bar-chart')),
]),
], width=5),
dbc.Col([
dbc.Row([
dbc.Col(),
]),
dbc.Row([
# insert bar chart
dbc.Col(dcc.Graph()),
], className="h-100"),
], width=5),
])
], fluid=True)
#app.callback(
[Output('bar-chart', 'figure')],
[Input("Type", "value")])
def generate_chart(value):
bar_data = df[df['Type'] == value]
count = bar_data['Type'].value_counts()
data = go.Bar(x = count.index, y = count.values)
layout = go.Layout(title = 'title')
fig = go.Figure(data = data, layout = layout)
return fig
if __name__ == '__main__':
app.run_server(debug=True)
I'm currently getting this error:
Traceback (most recent call last):
File "/Users/venv/lib/python3.9/site-packages/flask/app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/venv/lib/python3.9/site-packages/flask/app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/Users/venv/lib/python3.9/site-packages/dash/dash.py", line 1274, in dispatch
ctx.run(
File "/Users/venv/lib/python3.9/site-packages/dash/_callback.py", line 455, in add_context
flat_output_values = flatten_grouping(output_value, output)
File "/Users/venv/lib/python3.9/site-packages/dash/_grouping.py", line 35, in flatten_grouping
validate_grouping(grouping, schema)
File "/Users/venv/lib/python3.9/site-packages/dash/_grouping.py", line 210, in validate_grouping
SchemaTypeValidationError.check(grouping, full_schema, path, (tuple, list))
File "/Users/venv/lib/python3.9/site-packages/dash/_grouping.py", line 162, in check
raise SchemaTypeValidationError(value, full_schema, path, expected_type)
dash._grouping.SchemaTypeValidationError: Schema: [<Output `bar-chart.figure`>]
Path: ()
Expected type: (<class 'tuple'>, <class 'list'>)
Received value of type <class 'plotly.graph_objs._figure.Figure'>:
Figure({
'data': [{'type': 'bar', 'x': array([], dtype=object), 'y': array([], dtype=int64)}],
'layout': {'template': '...', 'title': {'text': 'title'}}
})
Your Output in the #app.callback decorator shouldn't be inside a list. If you change it to the following:
#app.callback(
Output('bar-chart', 'figure'),
[Input("Type", "value")])
def generate_chart(value):
bar_data = df[df['Type'] == value]
count = bar_data['Type'].value_counts()
data = go.Bar(x = count.index, y = count.values)
layout = go.Layout(title = 'title')
fig = go.Figure(data = data, layout = layout)
return fig
Then your app runs and responds correctly to radio item selection, as shown below.

plotly dash range slider with datetime and scatterplot interaction

I would like to add a range slider along with my dropdown, and make the range slider the 'Wallclock' datetime along with an interaction that allows the range slider to chose the datetime for that capsules based on the dropdown value. I managed to find several ways that other people have done this but none seems to work for my situation especially the callback and the update of the graph. Thank you!
Data looks like this.
Dash looks like this.
Code looks like this.
import pandas as pd
import plotly.express as px # (version 4.7.0)
import plotly.graph_objects as go
import numpy as np
import openpyxl
import dash # (version 1.12.0) pip install 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
app = dash.Dash(__name__)
server = app.server
df = pd.read_excel("tcd vs rh 2.xlsx")
print(df)
capsuleID = df['Capsule_ID'].unique()
print(capsuleID)
capsuleID_names = sorted(list(capsuleID))
print(capsuleID_names)
capsuleID_names_1 = [{'label': k, 'value': k} for k in sorted(capsuleID)]
capsuleID_names_2 = [{'label': '(Select All)', 'value': 'All'}]
capsuleID_names_all = capsuleID_names_1 + capsuleID_names_2
app.layout = html.Div([
html.H1("Relative Humidity vs TCD", style={'text-align': 'center'}),
dcc.Dropdown(id="capsule_select",
options=capsuleID_names_all,
optionHeight=25,
multi=True,
searchable=True,
placeholder='Please select...',
clearable=True,
value=['All'],
style={'width': "100%"}
),
dcc.RangeSlider(id='slider',
min=df['Wallclock'].min(),
max=df['Wallclock'].max(),
value=[df.iloc[-101]['Wallclock'].timestamp(), df.iloc[-1]['Wallclock'].timestamp()]
),
html.Div([
dcc.Graph(id="the_graph"),
]),
])
# -----------------------------------------------------------
#app.callback(
Output('the_graph', 'figure'),
Output('capsule_select', 'value'),
Input('capsule_select', 'value'),
Input('slider', 'value'),
)
def update_graph(capsule_chosen):
lBound = pd.to_datetime(value[0], unit='s')
uBound = pd.to_datetime(value[1], unit='s')
filteredData = df.loc[(df['date'] >= lBound) & (df['date'] <= uBound)]
dropdown_values = capsule_chosen
if "All" in capsule_chosen:
dropdown_values = capsuleID_names
dff = df
else:
dff = df[df['Capsule_ID'].isin(capsule_chosen)] # filter all rows where capsule ID is the capsule ID selected
scatterplot = px.scatter(
data_frame=dff,
x="tcd",
y="humidity",
hover_name="Wallclock",
)
scatterplot.update_traces(textposition='top center')
return scatterplot, dropdown_values
# ------------------------------------------------------------------------------
if __name__ == '__main__':
app.run_server(debug=True)
obviously I don't have access to your Excel spreadsheet so generated a data frame with same shape
taken approach of using a second figure with a rangeslider for slider capability
updated callback to use this figure as input for date range
used jupyter dash inline, this can be changed back to your setup (commented lines)
generate some sample data
import pandas as pd
import numpy as np
df = pd.DataFrame(
{
"Wallclock": pd.date_range(
"22-dec-2020 00:01:36", freq="5min", periods=2000
),
"tcd": np.linspace(3434, 3505, 2000) *np.random.uniform(.9,1.1, 2000),
"humidity": np.linspace(63, 96, 2000),
}
).pipe(lambda d: d.assign(Capsule_ID=(d.index // (len(d)//16))+2100015))
slider is a figure with a rangeslider
import pandas as pd
import plotly.express as px # (version 4.7.0)
import plotly.graph_objects as go
import numpy as np
import openpyxl
import dash # (version 1.12.0) pip install 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
from jupyter_dash import JupyterDash
# app = dash.Dash(__name__)
# server = app.server
app = JupyterDash(__name__)
# df = pd.read_excel("tcd vs rh 2.xlsx")
# print(df)
capsuleID = df["Capsule_ID"].unique()
# print(capsuleID)
capsuleID_names = sorted(list(capsuleID))
# print(capsuleID_names)
capsuleID_names_1 = [{"label": k, "value": k} for k in sorted(capsuleID)]
capsuleID_names_2 = [{"label": "(Select All)", "value": "All"}]
capsuleID_names_all = capsuleID_names_1 + capsuleID_names_2
def slider_fig(df):
return px.scatter(
df.groupby("Wallclock", as_index=False).size(), x="Wallclock", y="size"
).update_layout(
xaxis={"rangeslider": {"visible": True}, "title":None},
height=125,
yaxis={"tickmode": "array", "tickvals": [], "title": None},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
app.layout = html.Div(
[
html.H1("Relative Humidity vs TCD", style={"text-align": "center"}),
dcc.Dropdown(
id="capsule_select",
options=capsuleID_names_all,
optionHeight=25,
multi=True,
searchable=True,
placeholder="Please select...",
clearable=True,
value=["All"],
style={"width": "100%"},
),
dcc.Graph(
id="slider",
figure=slider_fig(df),
),
html.Div(
[
dcc.Graph(id="the_graph"),
]
),
]
)
# -----------------------------------------------------------
#app.callback(
Output("the_graph", "figure"),
Output("capsule_select", "value"),
Output("slider", "figure"),
Input("capsule_select", "value"),
Input('slider', 'relayoutData'),
State("slider", "figure")
)
def update_graph(capsule_chosen, slider, sfig):
dropdown_values = capsule_chosen
if "All" in capsule_chosen:
dropdown_values = capsuleID_names
dff = df
else:
dff = df[
df["Capsule_ID"].isin(capsule_chosen)
] # filter all rows where capsule ID is the capsule ID selected
if slider and "xaxis.range" in slider.keys():
dff = dff.loc[dff["Wallclock"].between(*slider["xaxis.range"])]
else:
# update slider based on selected capsules
sfig = slider_fig(dff)
scatterplot = px.scatter(
data_frame=dff,
x="tcd",
y="humidity",
hover_name="Wallclock",
)
scatterplot.update_traces(textposition="top center")
return scatterplot, dropdown_values, sfig
# ------------------------------------------------------------------------------
if __name__ == "__main__":
# app.run_server(debug=True)
app.run_server(mode="inline")

Dash dropdown with linechart

I'm trying to connect a dropdown in dash with a figure. I'm using the following code:
df = pd.read_csv('https://api.statbank.dk/v1/data/mpk100/CSV?valuePresentation=Value&timeOrder=Ascending&LAND=*&Tid=*', sep=';')
df = df[df['INDHOLD'] != '..']
df['rate'] = df['INDHOLD'].str.replace(',', '.').astype(float)
df_countries = df['LAND'].unique()
df['TID'] = pd.to_datetime(df['TID']) #datetime
df.groupby('LAND')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
# Create server variable with Flask server object for use with gunicorn
server = app.server
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(id='linedropdown',
options=[{'label': i, 'value': i} for i in df_countries],
value='DANMARK',
multi=True,
clearable=False
),
],className='six columns'),
],className='row'),
html.Div([
html.Div([
dcc.Graph(id='linechart'),
],className='six columns'),
],className='row'),
])
#app.callback(
[Output('linechart', 'figure')],
[Input('linedropdown', 'value')]
)
def update_graph(linedropval):
df_filterd = df[df['LAND'].isin(['INDHOLD'])]
#extract list of chosen countries
list_chosen_countries=df_filterd['LAND'].tolist()
#filter original df according to chosen countries
#because original df has all the complete dates
df_line = df[df['LAND'].isin(list_chosen_countries)]
line_chart = px.line(
data_frame=df_line,
x='TID',
y=linedropval,
color='LAND',
labels={'Rate':'rate', 'Datetime':'date'},
)
line_chart.update_layout(uirevision='foo')
return (line_chart)
#------------------------------------------------------------------
app.run_server()
But I'm getting the following error in the dashboard:
ValueError: All arguments should have the same length. The length of
column argument `df[color]` is 0, whereas the length of previously-
processed arguments ['TID', 'y'] is 1
and
ValueError: Value of 'y' is not the name of a column in 'data_frame'.
Expected one of ['LAND', 'TID', 'INDHOLD', 'rate'] but received: DANMARK
How can i tackle this? The dropdown includes countries with their respectice interest rates over years. This should be simple. But i have issues with the callback.
While all the columns in your dataframe are upper-case:
Index(['LAND', 'TID', 'INDHOLD', 'rate'], dtype='object')
All strings in the column 'LAND' are mixed case:
array(['Belgien', 'Bulgarien', 'Danmark', 'Estland', 'Finland',
'Frankrig', 'Grækenland', 'Irland', 'Island', 'Italien', 'Letland',
'Litauen', 'Luxembourg', 'Nederlandene', 'Norge', 'Polen',
'Portugal', 'Rumænien', 'Rusland', 'Schweiz', 'Slovakiet',
'Slovenien', 'Spanien', 'Storbritannien', 'Sverige', 'Tjekkiet',
'Tyskland', 'Ungarn', 'Østrig', 'Sydafrika', 'Canada', 'Mexico',
'USA', 'Israel', 'Indien', 'Japan', 'Sydkorea', 'Tyrkiet',
'Australien', 'New Zealand', 'Euro-dollar-renten'], dtype=object)
And you're trying to reference all countries here using only uppper-case like 'DANMARK'.
Correcting that will launch the app with a working selector. The figure doesn't quite work though since your filtering is a bit weird. Let me know what you're trying to achieve here and we can take a look at that too.
Figure / App
Complete code:
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
df = pd.read_csv('https://api.statbank.dk/v1/data/mpk100/CSV?valuePresentation=Value&timeOrder=Ascending&LAND=*&Tid=*', sep=';')
df = df[df['INDHOLD'] != '..']
df['rate'] = df['INDHOLD'].str.replace(',', '.').astype(float)
df_countries = df['LAND'].unique()
df['TID'] = pd.to_datetime(df['TID']) #datetime
df.groupby('LAND')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = JupyterDash(__name__, external_stylesheets=external_stylesheets)
# Create server variable with Flask server object for use with gunicorn
server = app.server
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(id='linedropdown',
options=[{'label': i, 'value': i} for i in df_countries],
value='Danmark',
multi=True,
clearable=False
),
],className='six columns'),
],className='row'),
html.Div([
html.Div([
dcc.Graph(id='linechart'),
],className='six columns'),
],className='row'),
])
#app.callback(
[Output('linechart', 'figure')],
[Input('linedropdown', 'value')]
)
def update_graph(linedropval):
#global df_filtered
global df_line
df_filtered = df[df['LAND'].isin(['INDHOLD'])]
#extract list of chosen countries
list_chosen_countries=df_filterd['LAND'].tolist()
#filter original df according to chosen countries
#because original df has all the complete dates
df_line = df[df['LAND'].isin(list_chosen_countries)]
line_chart = px.line(
data_frame=df_line,
x='TID',
y=linedropval,
color='LAND',
labels={'Rate':'rate', 'Datetime':'date'},
)
line_chart.update_layout(uirevision='foo')
return (line_chart)
#------------------------------------------------------------------
# Run app and display result inline in the notebook
app.enable_dev_tools(dev_tools_hot_reload =True)
app.run_server(mode='inline', port = 8040, dev_tools_ui=True, debug=True,
dev_tools_hot_reload =True, threaded=True)

Error in displaying multiple line plots on dash-plotly

I have a code where I try to draw a multiple line plot using plotly. The graph tries to plot the population of each town over the decade.
This is my implementation :
import pandas as pd
import plotly.express as px
import plotly.graph_objs as go
import dash_html_components as html
import dash_core_components as dcc
import dash
import os
root = os.getcwd()
df = pd.read_excel(os.path.join(root, 'data', 'DCHB_Town_Release_3500.xlsx'))
# df.fillna(0, inplace=True)
df_growth = df.set_index('Town Name')
census = [column for column in df.columns if "Town Population" in column]
app = dash.Dash()
app.title = 'Town Amenities'
male_population = go.Bar(
x=df['Town Name'],
y=df['Total Male Population of Town'],
name='Male'
)
female_population = go.Bar(
x=df['Town Name'],
y=df['Total Female Population of Town'],
name='Female'
)
census_years = [int(a.split('Census')[1].split(')')[0].strip()) for a in census]
app.layout = html.Div(
html.Div([
html.H1(children='Town Amenities'),
html.Div(children='Dashboard'),
dcc.Graph(
id='Total Population and Household',
figure={
'data': [
{'x': df['Town Name'], 'y': df['Total Households '],
'type': 'bar', 'name':'Total Households'},
{'x': df['Town Name'], 'y': df['Total Population of Town'],
'type':'bar', 'name':'Total Population'}
],
'layout': {
'title': 'Population and Household'
}
}
),
dcc.Graph(
id='Population Distribution',
figure=go.Figure(data=[male_population, female_population],
layout=go.Layout(barmode='stack'))
),
dcc.Graph(
id='Areas',
figure=go.Figure(data=[go.Pie(labels=df['Town Name'],
values=df['Area (sq. km.)'],
pull=[0, 0, 0.2, 0])])
),
dcc.Graph(
figure=go.Figure()
for col in list(df['Town Name']):
x=census
y_temp=df_growth.loc[col]
y=[y_temp[col] for col in census]
figure.add_trace(
go.Scatter(x=x, y=y,
name=col,
mode='markers+lines',
line=dict(shape='linear'),
connectgaps=True
)
)
)
])
)
I get an error in this line : for col in list(df['Town Name']): as invalid syntax (line is present in last dcc.Graph section). I don't know why as I tried it separately in jupyter notebook and it worked perfectly. Maybe the problem is that I use it within a dcc.Graph
This code worked perfectly :
fig = go.Figure()
for col in df['Town Name']:
x = census
y_temp = df_growth.loc[col]
y = [y_temp[col] for col in census]
fig.add_trace(go.Scatter(x=x, y=y,
name = col,
mode = 'markers+lines',
line=dict(shape='linear'),
connectgaps=True
)
)
fig.show()
Desired output
I replaced the dcc.Graph block with the following piece of code :
machines = [town for town in df['Town Name'] for i in range(len(census))]
units = [df_growth.loc[town][col] for town in df['Town Name'] for col in census]
time = census*len(df['Town Name'])
dcc.Graph(
figure=px.line(dict(machines=machines, units=units, time=time),
x='time', y='units', color='machines')
# figure.update_traces(mode='markers+lines')
# fig.show()
)
and it worked. I am not sure how to correct that code, but functions like update_trace and show can be used only on jupyter notebook.

DataTable and Map componant Side by Side or Horizontal to each other

I'm having so many issues align my map componants to the left of my data grid componant. I want each componant side by side. I have tried adding Divs, included attibutes and changing style. Please help.
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_leaflet as dl
import pandas as pd
import numpy as np
import dash_table_experiments as dt
lats = [28.538330, 34.729542, 40.712776]
lons = [-81.378883, -86.585297, -74.005974]
df = pd.DataFrame(columns=["lat", "lon"], data=np.column_stack((lats, lons)))
markers = [dl.Marker(position=[row["lat"], row["lon"]]) for i, row in df.iterrows()]
app = dash.Dash()
app = dash.Dash(external_stylesheets=['https://codepen.io/chriddyp/pen/bWLwgP.css'])
df = pd.read_csv('Foundational Data-LA057.csv')
def generate_table(dataframe, max_rows=10):
return html.Table([
html.Thead(
html.Tr([html.Th(col) for col in dataframe.columns])
),
html.Tbody([
html.Tr([
html.Td(dataframe.iloc[i][col]) for col in dataframe.columns
]) for i in range(min(len(dataframe), max_rows))
])
])
colors = {
'background': '#111111',
'text': '#7FDBFF'
}
app.layout = html.Div([
html.Div(
className="row",
children=[
html.Div([dl.Map(children=[dl.TileLayer(url="https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"), dl.LayerGroup(markers)],
style={'width': "100%", 'height': "100%"}, center=[38.627003, -90.199402], zoom=4, id="map"),
], style={'width': '600px', 'height': '500px'}),
generate_table(df)
]
)
])
if __name__ == '__main__':
app.run_server(debug=True)

Categories