Table creation with Dash Framework - python

I am trying to build a dashboard where user can choose a pandas dataframe from the dropdown. Also they can search, sort, see the summary and download the data.
I have designed the dropdown many with the file names. Also added the dash.DataTable component. But I am not able to call the dataframe based on the value selected from dropdown.
Code:
import dash
from dash.dependencies import Input, Output
from dash import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
#df = pd.read_csv('data/chronos.csv')
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
id='demo-dropdown',
options=[
{'label': 'Chronos_data', 'value': 'chronos.csv'},
{'label': 'CN_data', 'value': 'cn.csv'},
{'label': 'Expression_data', 'value': 'expression.csv'}
],
value='dataset'
),
html.Div(id='dd-output-container'),
dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
],
data=df.to_dict('records'),
editable=True,
filter_action="native",
sort_action="native",
sort_mode="multi",
column_selectable="single",
row_selectable="multi",
row_deletable=True,
selected_columns=[],
selected_rows=[],
page_action="native",
page_current= 0,
page_size= 15,
export_format='xlsx',
export_headers='display',
merge_duplicate_headers=True
),
html.Div(id='datatable-interactivity-container')
])
#app.callback(
Output('datatable-interactivity', 'data'),
[Input('demo-dropdown', 'value')]
)
def update_output(dropdown_val):
df_data = pd.read_csv('data/'+dropdown_val)
return df_data
#app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
[Input('datatable-interactivity', 'selected_columns')]
)
def update_styles(selected_columns):
return [{
'if': { 'column_id': i },
'background_color': '#D2F3FF'
} for i in selected_columns]
if __name__ == '__main__':
app.run_server(debug=True)
Error: line 27, in <module>
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
NameError: name 'df' is not defined
Thanks in advance.

Got the answer.
#app.callback(
Output('datatable-interactivity', 'data'),
Output('datatable-interactivity', 'columns'),
[Input('demo-dropdown', 'value')]
)
def update_output(dropdown_val):
df_data = pd.read_csv('data/'+dropdown_val)
return df_data,
[{"name": i, "id": i, "deletable": True, "selectable": True} for i in df_data.columns]

Related

How to display a Dash table inside an HTML container?

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)
]),

JupyterDash - Invalid argument `options` passed into Dropdown with ID

I am trying to create a dashboard to show the ethnicity makeup in different cities for multiple years. My dataframe consists of Year, Month, City and Native variables. I pasted an image on the bottom that shows my dataframe. I also tried to replicate a Dash code that I have but I received multiple errors after executing it, and it looks like most of the errors are about the City variable. Is there any guide to get my dash to work?
import dash
from jupyter_dash import JupyterDash # pip install dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
#df
import dash
from jupyter_dash import JupyterDash # pip install dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
#df
app = JupyterDash()
app.layout = html.Div([
html.H1("Native Country of Father"),
dcc.Dropdown(
id='cities',
options=[{'label': i, 'value': i} for i in list(df.City.unique()) + ['All']],
value='All'
),
dcc.RadioItems(
id='xaxis-type',
options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],
value='Log',
labelStyle={'display': 'inline-block'}
),
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
id='year-slider',
min=df['Year'].min(),
max=df['Year'].max(),
value=df['Year'].min(),
step=None,
marks={str(Year): str(Year) for Year in df['Year'].unique()}
)
],
style={'width': '48%', 'display': 'inline-block'})
#app.callback(
Output('graph-with-slider', 'figure'),
[Input('year-slider', 'value'),
Input('xaxis-type','value'),
Input('cities','value')])
def update_figure(selected_year, axis_type, City):
if City=="All":
filtered_df = df
else:
filtered_df = df[df['City']==City]
filtered_df = filtered_df[filtered_df.Year == selected_year]
traces = []
for i in filtered_df.City.unique():
df_by_City = filtered_df[filtered_df['City'] == i]
traces.append(go.Scatter(
y=df_by_City['Native Country of Father'],
text=df_by_City['Native Country of Father'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
))
return {
'data': traces,
'layout': go.Layout(
xaxis={'type': 'linear' if axis_type == 'Linear' else 'log',
'title': 'GDP Per Capita'},
yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
legend={'x': 0, 'y': 1},
hovermode='closest'
)
}
if __name__ =='__main__':
app.run_server(mode="external")
To get the dropdown working properly, you'll have to fix the value passed to options. What you have is:
options=[{'label': i, 'value': i} for i in list(df.City.unique()) + ['All']]
If you remove ['All'] and change the value prop, it should work. In order to have a value that selects everything, you need something like
options=[
{'label': i, 'value': i} for i in list(df.City.unique())
] + [{'label': 'All', 'value': 'All'}]

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.

Can I make a node clickable in dash as a hyperlink?

I have this code (from here) and it generates a network as expected:
import dash
import dash_core_components as dcc
from dash import html
import dash_cytoscape as cyto
from dash.dependencies import Input, Output
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.P("Dash Cytoscape:"),
cyto.Cytoscape(
id='cytoscape',
elements=[
{'data': {'id': 'ca', 'label': 'Canada'}},
{'data': {'id': 'on', 'label': 'Ontario'}},
{'data': {'id': 'qc', 'label': 'Quebec'}},
{'data': {'source': 'ca', 'target': 'on'}},
{'data': {'source': 'ca', 'target': 'qc'}}
],
layout={'name': 'breadthfirst'},
style={'width': '1000px', 'height': '1000px'}
)
])
if __name__ == '__main__':
app.run_server()
I'm just wondering, would someone know if I'm able to/how to edit this code so that I can click on a node, and it's a hyperlink to a webpage (e.g. in this case could just be the wikipedia page for each node).
You could create a callback which sets the href property of a dcc.Location component based on the clicked node:
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Location(id="location"),
cyto.Cytoscape(
id="cytoscape",
elements=[
{"data": {"id": "ca", "label": "Canada"}},
{"data": {"id": "on", "label": "Ontario"}},
{"data": {"id": "qc", "label": "Quebec"}},
{"data": {"source": "ca", "target": "on"}},
{"data": {"source": "ca", "target": "qc"}},
],
layout={"name": "breadthfirst"},
style={"width": "1000px", "height": "1000px"},
),
]
)
#app.callback(
Output("location", "href"),
Input("cytoscape", "tapNodeData"),
prevent_initial_call=True,
)
def navigate_to_url(node_data):
return f"https://en.wikipedia.org/wiki/{node_data['label']}"

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