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.
Related
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)
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")
I just started learning dash plotly. There are no problems with building a drawing. I think this is a great library for data visualization. But I ran into the fact that the data in the chart is not updated. My data is in the database and is being recorded all the time. I am using pandas for rendering.
Here is my code:
import sqlite3
import pandas as pd
from datetime import datetime
import pytz
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
timezone = pytz.timezone("Etc/UTC")
utc_from = datetime(2021, 3, 23, tzinfo=timezone)
#Создает новый файл , если он есть то просто подключается
base = sqlite3.connect('base_eurousd.db')
cur = base.cursor()
read_db = cur.execute('SELECT * FROM data_eurusd').fetchall()
df = pd.DataFrame(read_db)
#d = pd.read_sql("select * from data", db_conn)
print(df)
df[0] = pd.to_datetime(df[0], unit='ms')
df[3] = np.where(df[1].diff().lt(0)|df[2].diff().lt(0), df[3]*-1, df[3])
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.H2(children='My first dash'),
html.Div(children='''Dash : A web application framework for Python'''),
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x':df[0], 'y':df[1], 'name': 'BID', 'marker': {'color': 'red'}},
{'x':df[0], 'y':df[2], 'name': 'ASK', 'marker': {'color': 'blue'}},
],
'layout' : {
'title': 'TEST'
}
}
)
])
if __name__ == '__main__' :
app.run_server(debug=True)
df output:
0 1 2 3
0 1623066946305 1.21623 1.21625 2
1 1623066946432 1.21622 1.21625 2
2 1623066947746 1.21621 1.21624 6
3 1623066949244 1.21621 1.21623 4
4 1623066949587 1.21621 1.21624 4
... ... ... ... ..
85715 1623171716674 1.21840 1.21842 2
85716 1623171716808 1.21841 1.21843 6
85717 1623171717070 1.21841 1.21842 4
85718 1623171717419 1.21839 1.21841 6
85719 1623171717538 1.21838 1.21840 6
my question is: How can I launch the application and see the live update of the graph?
this is not the best version, but it allows you to clearly see how it works
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import sqlite3
import pytz
import pandas as pd
import numpy as np
from datetime import datetime
app = dash.Dash(__name__)
points = 0
def test():
global points
points += 1
def get_value(n_intervals):
timezone = pytz.timezone("Etc/UTC")
utc_from = datetime(2021, 3, 23, tzinfo=timezone)
base = sqlite3.connect('base_eurousd.db')
cur = base.cursor()
read_db = cur.execute('SELECT * FROM data_eurusd').fetchall()
df = pd.DataFrame(read_db)
# d = pd.read_sql("select * from data", db_conn)
df[0] = pd.to_datetime(df[0], unit='ms')
df[3] = np.where(df[1].diff().lt(0) | df[2].diff().lt(0), df[3] * -1, df[3])
#print(df)
return df
def serve_layout():
return html.Div(
children=[
html.H4(children='Доска'),
html.Div(id='my-id', children='''EURUSD'''),
dcc.Graph(id='example-graph', animate=True, responsive=True),
dcc.Interval(
id='interval-component',
interval=3 * 1000,
n_intervals=0,
),
],
)
app.layout = serve_layout
#app.callback(
Output('example-graph','figure'),
[Input('interval-component', 'n_intervals')])
def update_graph(n_intervals):
df = get_value(n_intervals)
test()
return \
{
'data': [
{'x': df[0], 'y': df[1], 'type': 'line', 'name': 'BID'},
{'x': df[0], 'y': df[2], 'type': 'line', 'name': 'ASK'},
],
'layout': go.Layout(xaxis=dict(range=[min(df[0]),max(df[0])]),yaxis=dict(range=[min(df[1]),max(df[2])]),)
}
if __name__ == '__main__':
app.run_server(debug=True)
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.
I have a simple database as in the below picture:
and the query looks like:
SELECT
[Date]
,[eNodeBName]
,[Downlinkbandwidth]
,[DownlinkEARFCN]
,[CellName]
,[LocalCellId]
,[PhysicalcellID]
,[LRRCConnReqAtt]
,[RRCSetupSuccessRate]
,[InterFreqSuccessRate4G]
,[IntraRATHOSucccessRate]
,[IntraFreqSuccessRate4G]
,[CellDLMaxThroughputMbps]
,[CellDownlinkAverageThroughputMbps]
FROM [myDB].[dbo].[input]
Now I need to create an interactive chart which depends on inputs like a date picker and drop down list.
As this is the sample GUI I created to figure chart throw this inputs as shown in the below picture:
Now I am creating chart based on the below columns name as in the below picture:
as this is the related query as the below:
SELECT
[Date]
,[CellName]
,[LRRCConnReqAtt]
,[RRCSetupSuccessRate]
,[InterFreqSuccessRate4G]
,[IntraRATHOSucccessRate]
,[IntraFreqSuccessRate4G]
,[CellDLMaxThroughputMbps]
,[CellDownlinkAverageThroughputMbps]
FROM [myDB].[dbo].[input]
So now the X-axis should be the Date column and the y-axis related to those below columns is the KPI columns:
SELECT
[LRRCConnReqAtt]
,[RRCSetupSuccessRate]
,[InterFreqSuccessRate4G]
,[IntraRATHOSucccessRate]
,[IntraFreqSuccessRate4G]
,[CellDLMaxThroughputMbps]
,[CellDownlinkAverageThroughputMbps]
FROM [myDB].[dbo].[input]
So now we have a unique column contains unique values is called CellName, this cell name I want create a simple chart for this unique value based on date columnn and KPI column.
So for example I want to show a line chart for a certain CellName = 2002334 for KPI LRRCConnReqAtt based on data from 27 of December to 9 of January. So I need a chart as the below picture and this is an example chart created in Excel.
and this is my code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
from sqlalchemy import create_engine
import datetime
from datetime import datetime as dt
from dash.dependencies import Input, Output
# connect db
engine = create_engine('mssql+pyodbc://xxxxxx\SMxxxxxARTRNO_EXPRESS/myDB?driver=SQL+Server+Native+Client+11.0')
cursor = engine.raw_connection().cursor()
start = datetime.datetime(2019, 12, 2)
end = datetime.datetime(2019, 12, 15)
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
lte_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[input]',
engine)
lte_kpis_raw = pd.read_sql('SELECT LRRCConnReqAtt, RRCSetupSuccessRate, InterFreqSuccessRate4G, IntraRATHOSucccessRate, IntraFreqSuccessRate4G,CellDLMaxThroughputMbps, CellDownlinkAverageThroughputMbps FROM [myDB].[dbo].[input]',
engine)
scale_1 = ['LRRCConnReqAtt']
scale_2 = ['RRCSetupSuccessRate', 'InterFreqSuccessRate4G', 'IntraRATHOSucccessRate', 'IntraFreqSuccessRate4G']
scale_3 = ['CellDLMaxThroughputMbps', 'CellDownlinkAverageThroughputMbps']
pd.set_option('display.max_columns', 500)
pd.set_option('display.width', 1000)
availble_cell = lte_kpis['CellName'].unique()
# availble_cell = lte_kpis.unique(lte_kpis[['Date', 'Site Name', 'Cell CI', 'Cell LAC']].values.ravel('K'))
app.layout = html.Div([
dcc.Dropdown(
id='cell-name-xaxis-column',
options=[{'label': i, 'value': i} for i in availble_cell],
value='2205516'
),
dcc.Dropdown(
id='myColumns',
options=[{'label': col, 'value': col} for col in lte_kpis_raw.columns],
multi=True,
value='LRRCConnReqAtt'
),
dcc.DatePickerRange(
id='my-date-picker-range',
min_date_allowed=dt(1995, 8, 5),
max_date_allowed=dt(2030, 9, 19),
initial_visible_month=dt(2019, 10, 5),
start_date=dt(2019, 10, 1),
end_date=dt(2020, 1, 1)
),
html.Div(id='output-container-date-picker-range'),
dcc.Graph(
style={'height': 300},
id='my-graph'
)
])
#app.callback(
Output('my-graph', 'figure'),
[Input('cell-name-xaxis-column', 'value'),
Input('myColumns', 'value')])
def update_graph(xaxis_column_name, yaxis_column_name, date_value):
dff = lte_kpis[lte_kpis['Date'] == date_value]
return {
'data': [dict(
x=dff[dff['Date'] == xaxis_column_name]['Value'],
y=dff[dff['Date'] == yaxis_column_name]['Value'],
text=dff[dff['Date'] == yaxis_column_name]['CellName'],
mode='line',
line={
'size': 15,
'opacity': 0.5
}
)],
}
if __name__ == '__main__':
app.run_server(debug=True)
Note that I want to put more than one KPI in one chart with different plots....
As the scale values in those KPI are little bit different so I tried to create a three types of objects with columns name scale values as the below code
scale_1 = ['LRRCConnReqAtt']
scale_2 = ['RRCSetupSuccessRate', 'InterFreqSuccessRate4G', 'IntraRATHOSucccessRate', 'IntraFreqSuccessRate4G']
scale_3 = ['CellDLMaxThroughputMbps', 'CellDownlinkAverageThroughputMbps']
and this is the error I found:
TypeError: update_graph() missing 1 required positional argument: 'date_value'
Traceback (most recent call last)
File "C:\Users\mwx825326\PycharmProjects\MyReference\venv\Lib\site-packages\dash\dash.py", line 1337, in add_context
output_value = func(*args, **kwargs) # %% callback invoked %%
TypeError: update_graph() missing 1 required positional argument: 'date_value'
Traceback (most recent call last):
File "C:\Users\mwx825326\PycharmProjects\MyReference\venv\Lib\site-packages\dash\dash.py", line 1337, in add_context
output_value = func(*args, **kwargs) # %% callback invoked %%
TypeError: update_graph() missing 1 required positional argument: 'date_value'
Any assistance appreciated.!!!!
Now this question is solved..
But I need it in more static way ,and the way I have to remove one Drop-down and create a chart based on one Drop-down and Date-Picker instead of 2 Drop-down as the removable drop down is based on Columns in DB in y-axis...
First I created Arrays for every Column should be the y-axis column, as I want to make it static charts for every multi or single Column in one Chart based on another Column or multiple Columns value in database....
as the below code:
SHOW_COLUMNS1 = [
'lrrc_re_est_succ',
'cell_dl_max_throughput'
]
SHOW_COLUMNS2 = [
'interfreq_success_rate_4g',
'intrarat_ho_success_rate'
]
SHOW_COLUMNS3 = [
'rcc_setup_success_rate',
'interfreq_success_rate_4g'
]
SHOW_COLUMNS4 = [
'cell_downlink_average_throughput'
]
after that the connection to the Date-Base
# connect db
engine = create_engine('mssql+pyodbc://xxxxxx\zzzzzz/myDB?driver=SQL+Server+Native+Client+11.0')
cursor = engine.raw_connection().cursor()
lte_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[lte_details]', engine)
after that I created a GUI for the interactive Charts and pandas read as the below code:
lte_kpis = pd.read_sql('SELECT * FROM [myDB].[dbo].[lte_details]', engine)
pd.set_option('display.max_columns', 10000)
print(lte_kpis)
lte_kpis.set_index('date', inplace=True)
availble_cell = lte_kpis['cell_name'].unique()
plots = []
app.layout = html.Div([
html.H5(
'Huawei KPI Dashbord'),
html.Label('Choose the "Cell-Name"'),
dcc.Dropdown(
id='cell-name-xaxis-column',
options=[{'label': i, 'value': i} for i in availble_cell],
value= availble_cell[0]
),
html.Label('Choose Date Destination'),
dcc.DatePickerRange(
id='date-picker-range',
min_date_allowed=dt(1995, 8, 5),
max_date_allowed=dt(2030, 9, 19),
initial_visible_month=dt(2019, 10, 5),
start_date=dt(2019, 10, 1),
end_date=dt(2020, 1, 1)
),
html.Div(id='output-container-date-picker-range-%s'),
dcc.Dropdown(
id='yaxis-columns',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS1],
multi=True,
disabled=True,
value=[SHOW_COLUMNS1[0], SHOW_COLUMNS1[1]]
),
dcc.Graph(
style={'height': 300},
id='my-graph'
),
dcc.Dropdown(
id='yaxis-columns2',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS2],
multi=True,
disabled=True,
value=[SHOW_COLUMNS2[0], SHOW_COLUMNS2[1]]
),
dcc.Graph(
style={'height': 300},
id='my-graph2'
),
dcc.Dropdown(
id='yaxis-columns3',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS3],
multi=True,
disabled=True,
value=[SHOW_COLUMNS3[0], SHOW_COLUMNS3[1]]
),
dcc.Graph(
style={'height': 300},
id='my-graph3'
),
dcc.Dropdown(
id='yaxis-columns4',
options=[{'label': col, 'value': col} for col in SHOW_COLUMNS4],
multi=True,
disabled=True,
value=[SHOW_COLUMNS4[0]]
),
dcc.Graph(
style={'height': 300},
id='my-graph4'
),
])
and this is Call-back
#app.callback(
Output(component_id='my-graph2', component_property='figure'),
[Input(component_id='cell-name-xaxis-column', component_property='value'),
Input(component_id='yaxis-columns2', component_property='value'),
Input(component_id='date-picker-range', component_property='start_date'),
Input(component_id='date-picker-range', component_property='end_date')])
def update_graph(cell_name, yaxis_cols, start_date, end_date):
if not isinstance(yaxis_cols, list):
yaxis_cols = [yaxis_cols]
print(yaxis_cols)
print((start_date, end_date))
sql_statement = "SELECT date, %s, %s FROM [myDB].[dbo].[lte_details] WHERE ([cell_name]='%s' AND [date]>='%s' AND [date]<='%s')" \
% (SHOW_COLUMNS2[0], SHOW_COLUMNS2[1], cell_name, start_date, end_date)
df = pd.read_sql(sql_statement, engine)
scatters = []
for col in yaxis_cols:
if col == 'lrrc_conn_req_att':
scatters.append(go.Bar(
x=df['date'],
y=df[col],
mode='lines',
name=col
))
else:
scatters.append(go.Scatter(
x=df['date'],
y=df[col],
name=col
))
figure = {
'data': scatters,
}
return figure
Note that as the previous error is related to the missing of data type in data base when importing the excel file to the data base related to the below Code:
col_dict = {
'date': 'Date',
'enodeb_name': 'eNodeB Name',
'downlink_bandwidth': 'Downlink bandwidth',
...........................
}
LTE_DETAILS_TABLE = 'lte_details'
cols = list(col_dict.keys())
# connect db
engine = create_engine('mssql+pyodbc://xxxxx\xxxxxx/myDB?driver=SQL+Server+Native+Client+11.0')
connection = engine.connect()
meta = MetaData()
ltedetails = Table(
LTE_DETAILS_TABLE, meta,
Column('id', Integer, primary_key=True),
Column(cols[0], Date),
Column(cols[1], String),
Column(cols[2], String),
.................................
)
if engine.dialect.has_table(engine, LTE_DETAILS_TABLE):
ltedetails.drop(engine)
meta.create_all(engine)
lte_df = pd.read_excel(os.path.join(os.path.dirname(__file__), 'input.xlsx'), sheet_name='LTE Details', dtype={
col_dict[cols[0]]: str,
col_dict[cols[1]]: str,
col_dict[cols[2]]: str,
.....................................
})
lte_df['Date'] = pd.to_datetime(lte_df['Date'], errors='coerce')
query = db.insert(ltedetails)
values_list = []
row_count = 1
for i in lte_df.index:
row = lte_df.loc[i]
record = {'id': row_count}
for col in col_dict.keys():
if col == cols[3] or col == cols[4] or col == cols[5] or col == cols[6] or col == cols[7] or col == cols[8]:
record[col] = int(row[col_dict[col]])
elif col == cols[9] or col == cols[10] or col == cols[11] or col == cols[12] or col == cols[13] or col == cols[14]:
record[col] = float(row[col_dict[col]])
else:
record[col] = row[col_dict[col]]
values_list.append(record)
row_count += 1
ResultProxy = engine.execute(query, values_list)
connection.close()
engine.dispose()
So I stuck now the I want to remove the Dropp-down with id ``which called id='yaxis-columns', ...
So If there's any comment about how to improve this code performance and Complete to solve my issue..
I am glad for that.