Hello everyone,
I’m working on my first application with Dash. I already posted a message previously and I got some help, thank you very much again.
For now, the app is displaying a table filtered by an input and then calculates some scores in two html.table during the app.callback steps. It was quite easy to develop this since the scores will be always displayed the same way, whatever the input is (each input has the same number of different scores).
Here’s my current issue. I want to display a third html.table. But, for this one, the number of records to display in the html.table depends of the number of row called by the input. I don’t know if what I say is clear or not so I put two screenshots at the end of this post. Sorry, it’s in French. As you can see if I choose the pizzas I got 6 ingredients, so I need 6 ids in my third html.table with the associated html.Th (“Jambon cuit”, “Gruyère”, etc). But if I choose the gâteaux et pâtisseries, then I need only 5 (and again, the html.Th should be set automatically).
Like I said it’s a little bit different from the two other tables I’ve got for now since for those ones the number of scores to calculate is fixed. The input is only used to make each calculation. I put a third screenshot with one example.
Could you give me an advice on how to make what I need? If I understood well, the calculation and algorithms are done in the app.callback steps, so I’m not sure what I should do in the layout to get what I want.
I also put my code at the end of this post. Thank you very much if you can give me an advice to follow.
Alpy
# =============================================================================
# Initialization
# =============================================================================
# Packages
# --------
# Pandas
import pandas as pd
# Numpy
import numpy as np
# Functools
from functools import reduce
# Datetime timedelta
from datetime import timedelta
import os
import datetime
import sys
import random
# Plotly Dash
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_table
from dash.dependencies import Input, Output
from dash_table import DataTable
from dash.exceptions import PreventUpdate
# Plotly
import plotly.express as px
# =============================================================================
# Data importation
# =============================================================================
# AGRIBALYSE.xlsx
agribalyse = pd.ExcelFile (r'AGRIBALYSE.xlsx')
# Detail ingrédient sheet
tmp_ingredients = pd.read_excel(agribalyse, r'Detail ingredient')
# Detail étapes sheet
tmp_etapes = pd.read_excel(agribalyse, r'Detail etape')
# =============================================================================
# Data management
# =============================================================================
# Ingredients sheet
# -----------------
# Abribalyse database with fill-in of all missing rows for products
ingredients=tmp_ingredients.fillna(method='ffill')
# List of columns to display in the application
ingredients_tab_data_total=ingredients[["Nom Français", "Groupe d'aliment", "Sous-groupe d'aliment", "Ingredients"]]
ingredients_tab_data = ingredients_tab_data_total[ingredients_tab_data_total["Ingredients"] != "Total"]
# List of available products
available_produtcs = ingredients['Nom Français'].unique()
# Details sheet
# -------------
tmp_etapes_2 = pd.DataFrame(tmp_etapes.reset_index())
tmp_etapes_2.reset_index(inplace = True)
etapes = tmp_etapes_2[["Nom du Produit en Français", "DQR", "Agriculture_EF", "Transformation_EF", "Emballage_EF", "Transport_EF", "Supermarché et distribution_EF", "Consommation_EF", "Total_EF"]]
# =============================================================================
# Dash application
# =============================================================================
# Style sheet
# -----------
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
# Application call
# ----------------
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
html.Div([
html.H1('Agribalyse'),
html.Div('''
This is a database about food and ecology. The table below shows the products and ingredients.
'''),
html.H1(' '),
html.Div('''
Please choose the ingredient you want to get the ecological impact.
''')
]),
html.Div([
dcc.Dropdown(
id='select_column',
options=[{'label':i, 'value': i} for i in available_produtcs],
value='Pizza jambon fromage',
#value=[],
#multi=True
)
]),
dash_table.DataTable(
id='data_table',
columns=[{"name": i, "id": i} for i in ingredients_tab_data.columns],
data=ingredients_tab_data.to_dict("rows")
),
html.Div([
html.H1(" "),
html.H2('''
The ecological results are displayed below:
'''),
html.H1(' ')
]),
html.Div([
html.Table([
html.Tr([html.Th(['Indicateur']), html.Th(['Mesure']), html.Th(['Unité'])]),
html.Tr([html.Td(['Score unique EF']), html.Td(id='I01'), html.Td(['mPt/kg de produit'])]),
html.Tr([html.Td(['Changement climatique']), html.Td(id='I02'), html.Td(['kg CO2 eq/kg de produit'])]),
html.Tr([html.Td(["Appauvrissement de la couche d'ozone"]), html.Td(id='I03'), html.Td(['E-06 kg CVC11 eq/kg de produit'])]),
html.Tr([html.Td(['Rayonnements ionisants']), html.Td(id='I04'), html.Td(['kBq U-235 eq/kg de produit'])]),
html.Tr([html.Td(["Formation photochimique d'ozone"]), html.Td(id='I05'), html.Td(['E-03 kg NMVOC eq/kg de produit'])]),
html.Tr([html.Td(["Particules"]), html.Td(id='I06'), html.Td(['E-06 disease inc./kg de produit'])]),
html.Tr([html.Td(["Acidification terrestre et eaux douces"]), html.Td(id='I07'), html.Td(['mol H+ eq/kg de produit'])]),
html.Tr([html.Td(["Eutrophisation terreste"]), html.Td(id='I08'), html.Td(['mol N eq/kg de produit'])]),
html.Tr([html.Td(["Eutrophisation eaux douces"]), html.Td(id='I09'), html.Td(['E-03 kg P eq/kg de produit'])]),
html.Tr([html.Td(["Eutrophisation marine"]), html.Td(id='I10'), html.Td(['E-03 kg N eq/kg de produit'])]),
html.Tr([html.Td(["Utilisation du sol"]), html.Td(id='I11'), html.Td(['Pt/kg de produit'])]),
html.Tr([html.Td(["Écotoxicité pour écosystèmes aquatiques d'eau douce"]), html.Td(id='I12'), html.Td(['CTUe/kg de produit'])]),
html.Tr([html.Td(["Épuisement des ressources eau"]), html.Td(id='I13'), html.Td(['m3 depriv./kg de produit'])]),
html.Tr([html.Td(["Épuisement des ressources énergétiques"]), html.Td(id='I14'), html.Td(['MJ/kg de produit'])]),
html.Tr([html.Td(["Épuisement des ressources minéraux"]), html.Td(id='I15'), html.Td(['E-06 kg Sb eq/kg de produit'])])
],className="six columns"),
html.Table([
html.Tr([html.Th(['Impact par étapes du cycle de vie']), html.Th(['%'])]),
html.Tr([html.Td(['Agriculture']), html.Td(id='ICV01')]),
html.Tr([html.Td(['Transformation']), html.Td(id='ICV02')]),
html.Tr([html.Td(['Emballage']), html.Td(id='ICV03')]),
html.Tr([html.Td(['Transport']), html.Td(id='ICV04')]),
html.Tr([html.Td(["Supermarché et distribution"]), html.Td(id='ICV05')]),
html.Tr([html.Td(["Consommation"]), html.Td(id='ICV06')])
],className="six columns")
],className="row")
])
app.css.append_css({
'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'
})
# Display the table
@app.callback(
Output('data_table', 'data'),
Input('select_column', 'value')
)
def update_table(product):
data=ingredients_tab_data[ingredients_tab_data["Nom Français"] == product]
#data=ingredients_tab_data[ingredients_tab_data["Nom Français"].isin(product)]
return data.to_dict("rows")
# Display the scores
@app.callback(
Output('I01', 'children'),
Output('I02', 'children'),
Output('I03', 'children'),
Output('I04', 'children'),
Output('I05', 'children'),
Output('I06', 'children'),
Output('I07', 'children'),
Output('I08', 'children'),
Output('I09', 'children'),
Output('I10', 'children'),
Output('I11', 'children'),
Output('I12', 'children'),
Output('I13', 'children'),
Output('I14', 'children'),
Output('I15', 'children'),
Input('select_column', 'value')
)
def callback_score(product):
# Summary of scores
tmp_score_0 = ingredients[ingredients["Ingredients"] != "Total"]
tmp_score_1 = tmp_score_0[tmp_score_0["Nom Français"]== product]
I01 = "{:0.2f}".format(tmp_score_1["Score unique EF (mPt/kg de produit)"].sum())
I02 = "{:0.2f}".format(tmp_score_1["Changement climatique (kg CO2 eq/kg de produit)"].sum())
I03 = "{:0.2f}".format(tmp_score_1["Appauvrissement de la couche d'ozone (E-06 kg CVC11 eq/kg de produit)"].sum())
I04 = "{:0.2f}".format(tmp_score_1["Rayonnements ionisants (kBq U-235 eq/kg de produit)"].sum())
I05 = "{:0.2f}".format(tmp_score_1["Formation photochimique d'ozone (E-03 kg NMVOC eq/kg de produit)"].sum())
I06 = "{:0.2f}".format(tmp_score_1["Particules (E-06 disease inc./kg de produit)"].sum())
I07 = "{:0.2f}".format(tmp_score_1["Acidification terrestre et eaux douces (mol H+ eq/kg de produit)"].sum())
I08 = "{:0.2f}".format(tmp_score_1["Eutrophisation terreste (mol N eq/kg de produit)"].sum())
I09 = "{:0.2f}".format(tmp_score_1["Eutrophisation eaux douces (E-03 kg P eq/kg de produit)"].sum())
I10 = "{:0.2f}".format(tmp_score_1["Eutrophisation marine (E-03 kg N eq/kg de produit)"].sum())
I11 = "{:0.2f}".format(tmp_score_1["Utilisation du sol (Pt/kg de produit)"].sum())
I12 = "{:0.2f}".format(tmp_score_1["Écotoxicité pour écosystèmes aquatiques d'eau douce (CTUe/kg de produit)"].sum())
I13 = "{:0.2f}".format(tmp_score_1["Épuisement des ressources eau (m3 depriv./kg de produit)"].sum())
I14 = "{:0.2f}".format(tmp_score_1["Épuisement des ressources énergétiques (MJ/kg de produit)"].sum())
I15 = "{:0.2f}".format(tmp_score_1["Épuisement des ressources minéraux (E-06 kg Sb eq/kg de produit)"].sum())
return I01, I02, I03, I04, I05, I06, I07, I08, I09, I10, I11, I12, I13, I14, I15
# Display the ecological impact
@app.callback(
Output('ICV01', 'children'),
Output('ICV02', 'children'),
Output('ICV03', 'children'),
Output('ICV04', 'children'),
Output('ICV05', 'children'),
Output('ICV06', 'children'),
Input('select_column', 'value')
)
def callback_impact(product):
tmp_impact_1 = etapes[etapes["Nom du Produit en Français"]==product]
tmp_ICV01 = ((tmp_impact_1["Agriculture_EF"]/tmp_impact_1["Total_EF"])*100)
tmp_ICV02 = ((tmp_impact_1["Transformation_EF"]/tmp_impact_1["Total_EF"])*100)
tmp_ICV03 = ((tmp_impact_1["Emballage_EF"]/tmp_impact_1["Total_EF"])*100)
tmp_ICV04 = ((tmp_impact_1["Transport_EF"]/tmp_impact_1["Total_EF"])*100)
tmp_ICV05 = ((tmp_impact_1["Supermarché et distribution_EF"]/tmp_impact_1["Total_EF"])*100)
tmp_ICV06 = ((tmp_impact_1["Consommation_EF"]/tmp_impact_1["Total_EF"])*100)
ICV01 = round(tmp_ICV01, 1)
ICV02 = round(tmp_ICV02, 1)
ICV03 = round(tmp_ICV03, 1)
ICV04 = round(tmp_ICV04, 1)
ICV05 = round(tmp_ICV05, 1)
ICV06 = round(tmp_ICV06, 1)
return ICV01, ICV02, ICV03, ICV04, ICV05, ICV06
if __name__ == '__main__':
app.run_server(debug=True)