How to display a Dash table inside an HTML container? - python

I have a small issue with Dash Table.
What I want to do is to put the table "records" inside the HTML container "graphique3". I have two problems:
First, when I simply want to display the table, nothing appears, it's just a copy/paste of a template here: https://dash.plotly.com/datatable/style. It works when I make a new file though.
Second, if I put my table code inside the container "graphique3" I get this error message
SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='?" for data = OrderedDict
I don't understand what is the issue, since, as mentioned before, it works fine in a new file.
# Run this app with `python app.py` and
# visit http://127.0.0.1:8050/ in your web browser.
from dash import Dash, html, dcc, dash_table
import plotly.express as px
import pandas as pd
import dash_daq as daq
from collections import OrderedDict
app = Dash(__name__)
# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options
df = pd.DataFrame({
"Fruit": ["Apples", "Oranges", "Bananas", "test4", "test5", "test6","test7","test8","test9"],
"Amount": [4, 1, 2, 2, 4, 5, 9, 5, 6],
})
fig = px.bar(df, x="Fruit", y="Amount", barmode="group")
#Réduire l'espace entre les éléments
fig.update_layout(
margin=dict(l=5, r=5, t=5, b=5),
paper_bgcolor="white",
),
# Table to put inside the container "graphique4"
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_cell_conditional=[
{
'if': {'column_id': c},
'textAlign': 'left'
} for c in ['Date', 'Region']
],
style_data={
'color': 'black',
'backgroundColor': 'white'
},
style_data_conditional=[
{
'if': {'row_index': 'odd'},
'backgroundColor': 'rgb(220, 220, 220)',
}
],
style_header={
'backgroundColor': 'rgb(210, 210, 210)',
'color': 'black',
'fontWeight': 'bold'
}
)
app.layout = html.Div(className='dashboard', children=[
# ------ Graphiques --------
#Première row
html.Div(className='row1', style={'display': 'flex', 'justify-content': 'center'}, children=[
# Graphiques
html.Div(className='graphique1',children=[
dcc.Graph(
id='exemple-graph1',
figure=fig,
style={'flex-grow': '1', 'width':'900px'}
),
]),
html.Div(className='graphique2',children=[
dcc.Graph(
id='exemple-graph2',
figure=fig,
style={'flex-grow': '1', 'width':'900px'}
),
]),
]),
# Deuxième row
html.Div(className='row2', style={'display': 'flex', 'justify-content': 'center'}, children=[
# Graphiques
html.Div(className='graphique3', children=[
dcc.Graph(
id='exemple-graph3',
figure=fig,
#style={'display': 'flex', 'width': '500px'}
),
]),
html.Div(className='graphique4', children=[
daq.Gauge(
color={"gradient": True, "ranges": {"green": [0, 6], "yellow": [6, 8], "red": [8, 10]}},
value=2,
label='Temps avant la prochaine relève',
max=10,
min=0,
),
]),
html.Div(className='graphique5', children=[
dcc.Graph(
id='exemple-graph5',
figure=fig,
)
]),
]),
])
if __name__ == '__main__':
app.run_server(debug=True)
#lien tutoriel : https://towardsdatascience.com/dash101-part-2-prettify-dash-dashboard-with-css-and-python-3866c069a3b6

The following code fragment taken from the Dash Tutorial website generates a HTML table.
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))
])
])
Within your code you then call the function to generate the table and pass the dataframe as a parameter.
html.Div(className='graphique3', children=[
dcc.Graph(
id='exemple-graph3',
figure=fig,
#style={'display': 'flex', 'width': '500px'}
),
generate_table(df)
]),

Related

How to change the cell font size in a Plotly-Dash DataTable?

How do you change the font size of the information in the cells of a Dash DataTable using Python? It seems like style_cell or style_data is where I should be able to change the font size but it doesn't have an effect.
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_cell=[
{
'if': {'column_id': 'Region'},
'font_size': '28px',
'textAlign': 'left'
}
],
style_cell_conditional=[
{
'if': {'column_id': 'Region'},
'font_size': '28px',
'textAlign': 'left'
}
]
)
if __name__ == '__main__':
app.run_server(debug=True)

Python Dash app with excel-like feature to select column elements with dropdown

I am writing a dash app with following inputs like below:-
So far I've written the code as below:-
from dash import Dash, dcc, html, Input, Output, dash_table
import dash
from dash.dependencies import Input, Output, State
import dash
import pandas as pd
import dash_bootstrap_components as dbc
import io
import base64
import dash_renderer
def parse_contents(contents, filename):
# content_type, content_string = contents.split(',')
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
df1 = pd.read_excel(io.BytesIO(decoded), sheet_name='Sheet1')
df2 = pd.read_excel(io.BytesIO(decoded), sheet_name='Sheet2')
return df1, df2
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container([
dbc.Row(
dbc.Col(html.H1("Container Vulnerability Risk Rating Calculator",
className='text-center text-primary'),
width=12)
),
dbc.Row([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '30%',
'height': '40px',
'lineHeight': '40px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '0px'
},
multiple=False
)]
),
dbc.Row([
dbc.Col([
dash_table.DataTable(
id='no-dropdown',
fill_width=False,
columns=[
{'id': 'Microservices', 'name': 'Microservices'}
],
css=[ {"selector": ".Select-menu-outer", "rule": "display : block !important"} ],
style_cell={'textAlign': 'left'},
editable=False,
)
], width=5
),
dbc.Col([
dash_table.DataTable(
id='with-dropdown',
fill_width=False,
css=[ {"selector": ".Select-menu-outer", "rule": "display : block !important"} ],
# style_cell={'textAlign': 'left'},
columns=[
{'id': 'Hosting Environment', 'name': 'Hosting Environment', 'presentation': 'dropdown'},
{'id': 'Complexities', 'name': 'Complexities', 'presentation': 'dropdown'},
{'id': 'Criticality', 'name': 'Criticality', 'presentation': 'dropdown'}
],
editable=False,
)
], width=5
)
]
)
], fluid=True
)
#app.callback(
[
Output('no-dropdown', "data"),
Output('with-dropdown', 'dropdown'),
Output('with-dropdown', 'data')
],
Input('upload-data', 'contents'),
Input('upload-data', 'filename')
)
def load_data(contents, filename):
if contents is not None:
# contents = contents[0]
dff1, dff2 = parse_contents(contents, filename)
dropdown={
'Hosting Environment': {
'options': [
{'label': i, 'value': i} for i in dff2['Hosting Environment']
]
},
'Complexities': {
'options': [
{'label': i, 'value': i} for i in dff2['Complexities']
]
},
'Criticality': {
'options': [
{'label': i, 'value': i} for i in dff2['Criticality']
]
}
}
# print(dff['Hosting Environment'].unique())
return dff1['Microservices'].to_frame().to_dict('records'), dropdown, dff2[['Hosting Environment', 'Complexities', 'Criticality']].to_dict('records')
else:
# print(type([{}]))
return [{}], {}, [{}]
if __name__ == '__main__':
app.run_server(debug=True)
This program renders the Layout where the Microservices column renders fine as it has to be a static column but "Hosting Environment" and other columns highlighted in Yellow, should display a dropdown so that user can select various options.
I first thought that it's due to a bug in Bootstrap, which is well documented. but even after including the workaround code, this still doesn't work.
Any help would be greatly appreciated.

Arranging elements horizontally in a dash application

I'm trying to develop a Dash application in python. I tried adding style={'display': 'inline-block'} to the html.Div() component, as well as to other components, but couldn't set the drop-down menus to align in one row.
The page looks as follows:
with the inline styling:
Without the inline styling:
The code in the question was given to me as a template that needs to be filled properly. The complex hierarchy was part of the template. My job is to add code as needed. I'm adding only the problematic part of the code (without the title and the graph elements that are seen in the images):
df = pd.read_csv("dash\Pricing Data.csv")
colors = {
'background': '#111111',
'text': '#7FDBFF'
}
boxplot_layout = (
dbc.Container(
[dbc.Row(
[
dbc.Col(
[
dbc.Card(
[
dbc.CardBody(
[
dbc.Row(
[
dbc.Col(
html.Div(
dbc.Row(
[
dbc.Col(
[
dcc.Dropdown(
id="aggregate-dropdown",
options=[
{
"label": "Total",
"value": "sum",
},
{
"label": "Average",
"value": "average",
},
],
value="sum",
style={
'textAlign': 'center',
# 'color': colors['text']
},
)
],
),
dbc.Col(
[
dcc.Dropdown(
id="y-dropdown",
options=[
{'label': i, 'value': i}
for i in df.columns],
style={
'textAlign': 'center',
},
value='Age'
)
],
),
dbc.Col(
[
html.Label(
"by",
style={
'textAlign': 'center',
# 'color': colors['text']
}
)
],
),
dbc.Col(
[
dcc.Dropdown(
id="x-dropdown",
options=[
{'label': i, 'value': i}
for i in df.columns],
style={
'textAlign': 'center',
'padding': '3px ',
},
value='Age'
)],),],)))],),])],inverse=True,)])])]))
app.layout = boxplot_layout
if __name__ == "__main__":
app.run_server(debug=True)
Also, as can be seen in the images, there's an error message. I couldn't find solutions for this error, so if you have any ideas regarding its cause or how to find it I'll be grateful if you could post it too.
Thanks.
Following the doc example:
dbc.Row(
[
dbc.Col(html.Div("One of three columns")),
dbc.Col(html.Div("One of three columns")),
dbc.Col(html.Div("One of three columns")),
]
),
it results something you are chasing for. So, that's the basic structure, removing unnecessary code, follows:
import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import pandas as pd
df = pd.read_csv()
colors = {
'background': '#111111',
'text': '#7FDBFF'
}
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = html.Div([
dbc.Container([
dbc.Row([
dbc.Col(
html.Div([
dcc.Dropdown(
id="aggregate-dropdown",
options=[
{
"label": "Total",
"value": "sum",
},
{
"label": "Average",
"value": "average",
},
],
value="sum",
style={
'textAlign': 'center',
# 'color': colors['text']
},
)
]), width=3
),
dbc.Col(
html.Div([
dcc.Dropdown(
id="y-dropdown",
options=[
{'label': i, 'value': i}
for i in df.columns],
style={
'textAlign': 'center',
},
value='Age'
)
]), width=3
),
dbc.Col(
html.Div([
html.Label(
"by",
style={
'textAlign': 'center',
# 'color': colors['text']
}
)
]), width=1
),
dbc.Col(
html.Div([
dcc.Dropdown(
id="x-dropdown",
options=[
{'label': i, 'value': i}
for i in df.columns],
style={
'textAlign': 'center',
},
value='Age'
)
]), width=3
),
])
])
])
if __name__ == "__main__":
app.run_server(debug=True)
Note I passed a 'width=' keyword argument to set the size of columns.
And that's the result:
result
I hope it's that help you to find the better way to organize your code.
What I did eventually was to change the style inside the Column components of the Drop-down menus, as well as the style of the Drop-down themselves. I used the tags 'padding' and 'width' and changed their values until it looked OK. I also used the value 'inline-block' for the 'display' tag.
For instance, here's the code for one of the drop-down menus and it's column:
dbc.Col(
[
dcc.Dropdown(
id="y-axis-dropdown",
options=
[{'label': i, 'value': i} for i in df.columns],
value='Age',
style={'textAlign': 'center'}
)
], style={
'display': 'inline-block',
'width': '25%',
'padding': 30,
'textAlign': 'center'
}
)

How can callback handle variable number of multiple inputs in Dash

I would like to develop a program that is able to dynamically compute the mean for different types of distributions (normal, lognormal). The distribution functions require two respectively three input parameters.
My callback returns an: “A nonexistent object was used in an Input …” error since always three input parameters are passed to the function.
Does anyone have an idea how to solve this issue?
Thanks
import dash
from jupyter_dash import JupyterDash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
import plotly.graph_objs as go
import pandas as pd
import numpy as np
import scipy.stats as stats
#app = dash.Dash()
app = JupyterDash(external_stylesheets=[dbc.themes.BOOTSTRAP], suppress_callback_exceptions=True)
app.layout = html.Div([
dbc.Card(
dbc.CardBody([
dbc.Row([
dbc.Col([
dbc.Row([
dcc.Dropdown(
id='dd-dist',
clearable = False,
options=[
{'label': 'Normal', 'value': 'NOR'},
{'label': 'Log-Normal', 'value': 'LGN'},
],
style={'width': '60%'},
value='LGN'
)
],),
html.Div(
id='parameter-input'
),
dbc.Row([
dbc.Col([
html.H5('Mean')
],width={'size': 5, 'offset': 0}),
dbc.Col([
dcc.Input(
id='mean-out',
value= None,
)
])
]),
], width={'size': 4, 'offset': 0, 'order': 1}),
], align='center'),
])
)
], style={'padding': 10})
#app.callback(
Output('parameter-input', 'children'),
[Input('dd-dist', 'value')])
def update_parameter(value):
if 'LGN' == value:
return (dbc.Row([
dbc.Col([
html.H5('Shape')
],width={'size': 5, 'offset': 0}),
dbc.Col([
dcc.Input(
id='param1-in',
debounce = True,
value = 1,
min= 0,
max= 10,
style = {'fontSize': 14}
)
],width={'size': 4, 'offset': 0}, align='end')
]),
dbc.Row([
dbc.Col([
html.H5('Location')
],width={'size': 5, 'offset': 0}),
dbc.Col([
dcc.Input(
id='param2-in',
debounce = True,
value = 1,
min=0,
max=5,
style = {'fontSize': 14}
)
],width={'size': 4, 'offset': 0}, align='end')
]),
dbc.Row([
dbc.Col([
html.H5('Scale')
],width={'size': 5, 'offset': 0}),
dbc.Col([
dcc.Input(
id='param3-in',
debounce = True,
value = 1,
min=0,
max=5,
style = {'fontSize': 14}
)
],width={'size': 4, 'offset': 0}, align='end')
])
)
elif 'NOR' == value:
return (dbc.Row([
dbc.Col([
html.H5('Mean')
],width={'size': 5, 'offset': 0}),
dbc.Col([
dcc.Input(
id='param1-in',
debounce = True,
value = 1,
min= 0,
max= 10,
style = {'fontSize': 14}
)
],width={'size': 4, 'offset': 0}, align='end')
]),
dbc.Row([
dbc.Col([
html.H5('Standard deviation')
],width={'size': 5, 'offset': 0}),
dbc.Col([
dcc.Input(
id='param2-in',
debounce = True,
value = 1,
min=0,
max=5,
style = {'fontSize': 14}
)
],width={'size': 4, 'offset': 0}, align='end')
])
)
#app.callback(
Output('mean-out', 'value'),
[Input('dd-dist', 'value'),
Input('param1-in', 'value'),
Input('param2-in', 'value'),
Input('param3-in', 'value')
]
)
def return_mean(dist, param1, param2, param3):
if dist == 'LGN':
return round(stats.lognorm.mean(float(param1), float(param2), float(param3)), 3)
elif dist == 'NOR':
return round(stats.norm.mean(float(param1), float(param2)), 3)
if __name__ == '__main__':
app.run_server(mode='external')
I might be misinterpreting this but it seems to me like you want a varying number of arguments. The proper way to do this in python is this syntax:
def test(*args):
for arg in args:
print(arg)
This function will accept any number of inputs and print them in order as the *args creates a list of all the trailing arguments. It should be noted that positional arguments can still be placed before this and it will not raise an error if it receives no arguments, it only creates an empty list.
Make sure to comment if you have any questions or if this was not what you were asking for.

Pandas 'key' error while creating charts through Dash

I am trying to create a scatter plot between two metrics after asking for the dimension level drill down. However, I am getting the the error: KeyError: u’brand’(one of the column names). I am new do Dash and cannot debug the error because there is nothing wrong with the column name. Following is the code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import pandas as pd
import sqlalchemy as sq
import numpy as np
from datetime import datetime
engine_prd = sq.create_engine(“connection url”)
df=pd.read_sql(“SELECT t1.date,
t1.article_type as article_type,
t1.product_gender as product_gender,
t1.brand as brand,
t1.master_category as master_category,
t1.business_unit as business_unit,
SUM(t1.revenue) as revenue,
SUM(t1.sold_quantity) as units_sold,
SUM(t1.total_discount) / NULLIF( SUM(t1.total_mrp),0) AS discount_perc,
SUM(t1.approved_po_quantity) - SUM(t1.po_inwarded_quantity) AS pending_invard_quantity,
SUM(t1.revenue) / NULLIF(SUM(t1.list_count), 0) AS rpi,
SUM(t1.list_count),
100 *ratio_to_report(SUM(t1.list_count)) OVER (PARTITION BY t1.DATE) AS lc_share
FROM fact_category_over_view_metrics t1
WHERE t1.DATE> 20180101 and is_live_style=1
GROUP BY
t1.DATE,t1.article_type,t1.product_gender,t1.brand,t1.master_category,
t1.business_unit;”,engine_prd)
df[[‘date_format’]] = df[[‘date’]].applymap(str).applymap(lambda s: “{}/{}/{}”.format(s[4:6],s[6:], s[0:4]))
df[[‘year_month’]]=df[[‘date’]].applymap(str).applymap(lambda s: “{}-{}”.format(s[0:4],s[4:6]))
df[‘year_month’]=df[‘year_month’].astype(str)
year_month=df[‘year_month’].unique()
available_indicators = np.array([‘revenue’,‘units_sold’,‘discount_perc’,‘pending_invard_quantity’,‘rpi’,‘lc_share’])
dimension_level=np.array([‘brand’,‘product_gender’,‘article_type’,‘master_category’,‘business_unit’])
#available_indicators=list(df)
app=dash.Dash()
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
id='dimension-level',
options=[{'label': i, 'value': i} for i in dimension_level],
value='brand'
)]),
html.Div([
dcc.Dropdown(
id='crossfilter-xaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='revenue'
),
dcc.RadioItems(
id='crossfilter-xaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
],
style={'width': '48%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='crossfilter-yaxis-column',
options=[{'label': i, 'value': i} for i in available_indicators],
value='units_sold'
),
dcc.RadioItems(
id='crossfilter-yaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Linear',
labelStyle={'display': 'inline-block'}
)
], style={'width': '48%', 'float': 'right', 'display': 'inline-block'})
]),
dcc.Graph(
id='crossfilter-indicator-scatter'),
dcc.Slider(
id='crossfilter-year-month--slider',
min=0,
max=len(df['year_month'].unique()),
value=0,
step=None,
marks={i : str(yearm) for i, yearm in enumerate(df['year_month'].unique())} # enumerate the dates
)
])
#app.callback(
dash.dependencies.Output(‘crossfilter-indicator-scatter’, ‘figure’),
[dash.dependencies.Input(‘dimension-level’, ‘value’),
dash.dependencies.Input(‘crossfilter-xaxis-column’, ‘value’),
dash.dependencies.Input(‘crossfilter-yaxis-column’, ‘value’),
dash.dependencies.Input(‘crossfilter-xaxis-type’, ‘value’),
dash.dependencies.Input(‘crossfilter-yaxis-type’, ‘value’),
dash.dependencies.Input(‘crossfilter-year-month–slider’, ‘value’)],
[dash.dependencies.State(‘crossfilter-year-month–slider’, ‘marks’)])
def update_graph(dimension_level_name,xaxis_column_name, yaxis_column_name,xaxis_type, yaxis_type, selected_year_month_key,marks):
selected_year_month=marks[str(selected_year_month_key)]
df_filtered = df[df['year_month'] == selected_year_month]
dff=df_filtered.groupby([dimension_level_name]).sum()
return {
'data': [go.Scatter(
x=dff[xaxis_column_name],
y=dff[yaxis_column_name],
text=dff[dimension_level_name],
#customdata=dff['article_type'],
mode='markers',
marker={
'size': 15,
'opacity': 0.5,
'line': {'width': 0.5, 'color': 'white'}
}
)],
'layout': go.Layout(
xaxis={
'title': xaxis_column_name,
'type': 'linear' if xaxis_type == 'Linear' else 'log'
},
yaxis={
'title': yaxis_column_name,
'type': 'linear' if yaxis_type == 'Linear' else 'log'
},
margin={'l': 40, 'b': 30, 't': 10, 'r': 0},
height=450,
hovermode='closest'
)
}
if name == ‘main’:
app.run_server()
The errors occurs while grouping by the df using the input value from dropdown. The data frame’s head looks has been linked to The sample data:
The key error occurs in "text=dff[dimension_level_name]". It is because while grouping by the dataframe , as_index is not set to False. This will throw a key error. The problem was solved by replacing dff=df_filtered.groupby([dimension_level_name]).sum() with:
dff=df_filtered.groupby([dimension_level_name].as_index=False).sum()

Categories