Ajout de filtres et des donuts de catégorie #65

This commit is contained in:
Colin Maudry
2026-03-17 22:44:15 +01:00
parent 6c778882f9
commit c02fb995c5
4 changed files with 114 additions and 13 deletions
+7
View File
@@ -190,6 +190,13 @@ p.version > a {
grid-row: 1; grid-row: 1;
} }
/* --- Dashboard inputs --- */
.Select--multi .Select-value {
color: var(--primary-color);
background-color: rgba(255, 240, 240, 0.4);
}
/* --- Tables (Dash & Custom) --- */ /* --- Tables (Dash & Custom) --- */
/* Table Menu (Exports etc) */ /* Table Menu (Exports etc) */
+19
View File
@@ -624,6 +624,25 @@ def make_card(
return card return card
def make_donut(lff: pl.LazyFrame, names_col):
title = data_schema[names_col]["title"]
lff = lff.rename({names_col: title})
lff = lff.select("uid", title)
lff = lff.group_by(title).len("Nombre")
lff = lff.with_columns(pl.col(title).replace(None, pl.lit("?")))
fig = px.pie(
lff.collect(engine="streaming"),
values="Nombre",
names=title,
hole=0.4,
color_discrete_sequence=px.colors.qualitative.Safe,
)
fig = fig.update_traces(texttemplate="<b>%{label}</b><br><b>%{percent}</b>")
fig = fig.update_layout(showlegend=False, font=dict(size=14))
graph = dcc.Graph(figure=fig)
return graph
def make_column_picker(page: str): def make_column_picker(page: str):
table_data = [] table_data = []
table_columns = [ table_columns = [
+81 -6
View File
@@ -5,7 +5,7 @@ import polars as pl
import polars.selectors as cs import polars.selectors as cs
from dash import Input, Output, callback, dcc, html, register_page from dash import Input, Output, callback, dcc, html, register_page
from src.figures import get_geographic_maps, make_card from src.figures import get_geographic_maps, make_card, make_donut
from src.utils import ( from src.utils import (
departements, departements,
df, df,
@@ -69,7 +69,7 @@ layout = [
options=get_enum_values_as_dict( options=get_enum_values_as_dict(
"acheteur_categorie" "acheteur_categorie"
), ),
placeholder="Catégorie d'acheteur", placeholder="Catégorie",
), ),
), ),
dbc.Row( dbc.Row(
@@ -81,14 +81,44 @@ layout = [
options=options_departements, options=options_departements,
), ),
), ),
html.H5("Titulaire"),
dbc.Row(
dcc.Dropdown(
id="dashboard_titulaire_categorie",
placeholder="Catégorie",
options=get_enum_values_as_dict(
"titulaire_categorie"
),
),
),
html.H5("Marché"), html.H5("Marché"),
dbc.Row( dbc.Row(
dcc.Dropdown( dcc.Dropdown(
id="dashboard_marche_type", id="dashboard_marche_type",
placeholder="Type de marché", placeholder="Type",
options=get_enum_values_as_dict("type"), options=get_enum_values_as_dict("type"),
), ),
), ),
dbc.Row(
dcc.Dropdown(
id="dashboard_marche_considerationsSociales",
placeholder="Considérations sociales",
options=get_enum_values_as_dict(
"considerationsSociales"
),
multi=True,
),
),
dbc.Row(
dcc.Dropdown(
id="dashboard_marche_considerationsEnvironnementales",
placeholder="Considérations environnementales",
multi=True,
options=get_enum_values_as_dict(
"considerationsEnvironnementales"
),
),
),
], ],
), ),
dbc.Col( dbc.Col(
@@ -112,13 +142,19 @@ layout = [
Input("dashboard_year", "value"), Input("dashboard_year", "value"),
Input("dashboard_acheteur_categorie", "value"), Input("dashboard_acheteur_categorie", "value"),
Input("dashboard_acheteur_departement_code", "value"), Input("dashboard_acheteur_departement_code", "value"),
Input("dashboard_titulaire_categorie", "value"),
Input("dashboard_marche_type", "value"), Input("dashboard_marche_type", "value"),
Input("dashboard_marche_considerationsSociales", "value"),
Input("dashboard_marche_considerationsEnvironnementales", "value"),
) )
def udpate_dashboard_cards( def udpate_dashboard_cards(
dashboard_year, dashboard_year,
dashboard_acheteur_categorie, dashboard_acheteur_categorie,
dashboard_acheteur_departement_code, dashboard_acheteur_departement_code,
dashboard_titulaire_categorie,
dashboard_marche_type, dashboard_marche_type,
dashboard_marche_considerationsSociales,
dashboard_marche_considerationsEnvironnementales,
): ):
lff: pl.LazyFrame = df.lazy() lff: pl.LazyFrame = df.lazy()
lff = lff.select( lff = lff.select(
@@ -127,10 +163,14 @@ def udpate_dashboard_cards(
cs.starts_with("titulaire"), cs.starts_with("titulaire"),
"dateNotification", "dateNotification",
"montant", "montant",
"considerationsSociales",
"considerationsEnvironnementales",
) )
# Application des filtres # Application des filtres
## Période
if dashboard_year: if dashboard_year:
lff = lff.filter(pl.col("dateNotification").dt.year() == int(dashboard_year)) lff = lff.filter(pl.col("dateNotification").dt.year() == int(dashboard_year))
else: else:
@@ -138,6 +178,8 @@ def udpate_dashboard_cards(
pl.col("dateNotification") > (datetime.now() - timedelta(days=365)) pl.col("dateNotification") > (datetime.now() - timedelta(days=365))
) )
## Acheteur
if dashboard_acheteur_categorie: if dashboard_acheteur_categorie:
lff = lff.filter(pl.col("acheteur_categorie") == dashboard_acheteur_categorie) lff = lff.filter(pl.col("acheteur_categorie") == dashboard_acheteur_categorie)
@@ -148,12 +190,38 @@ def udpate_dashboard_cards(
) )
) )
## Titulaire
if dashboard_titulaire_categorie:
lff = lff.filter(pl.col("titulaire_categorie") == dashboard_titulaire_categorie)
## Marché
if dashboard_marche_type: if dashboard_marche_type:
lff = lff.filter(pl.col("type") == dashboard_marche_type) lff = lff.filter(pl.col("type") == dashboard_marche_type)
# Génération des métriques if dashboard_marche_considerationsSociales:
dff = lff.collect() lff = lff.filter(
pl.col("considerationsSociales")
.str.split(", ")
.list.set_intersection(dashboard_marche_considerationsSociales)
.list.len()
> 0
)
if dashboard_marche_considerationsEnvironnementales:
lff = lff.filter(
pl.col("considerationsEnvironnementales")
.str.split(", ")
.list.set_intersection(dashboard_marche_considerationsEnvironnementales)
.list.len()
> 0
)
# Génération des métriques
dff = lff.collect(engine="streaming")
# À transformer en fonction
nb_acheteurs = dff.select("acheteur_id").n_unique() nb_acheteurs = dff.select("acheteur_id").n_unique()
nb_titulaires = dff.select("titulaire_id", "titulaire_typeIdentifiant").n_unique() nb_titulaires = dff.select("titulaire_id", "titulaire_typeIdentifiant").n_unique()
@@ -165,7 +233,6 @@ def udpate_dashboard_cards(
cards = [] cards = []
# À transformer en fonction
card_basic_counts = [ card_basic_counts = [
html.P(["Nombre de marchés : ", html.Strong(str(format_number(nb_marches)))]), html.P(["Nombre de marchés : ", html.Strong(str(format_number(nb_marches)))]),
html.P( html.P(
@@ -179,6 +246,14 @@ def udpate_dashboard_cards(
cards.append(make_card(title="Résumé", paragraphs=card_basic_counts)) cards.append(make_card(title="Résumé", paragraphs=card_basic_counts))
donut_acheteur_categorie = make_donut(lff, "acheteur_categorie")
cards.append(make_card(title="Catégorie d'acheteur", fig=donut_acheteur_categorie))
donut_titulaire_categorie = make_donut(lff, "titulaire_categorie")
cards.append(
make_card(title="Catégorie d'entreprise", fig=donut_titulaire_categorie)
)
geographic_maps: list[dbc.Col] = get_geographic_maps(dff) geographic_maps: list[dbc.Col] = get_geographic_maps(dff)
return dbc.Row(children=cards + geographic_maps) return dbc.Row(children=cards + geographic_maps)
+7 -7
View File
@@ -697,13 +697,13 @@ def get_button_properties(height):
def get_enum_values_as_dict(column_name): def get_enum_values_as_dict(column_name):
for column in data_schema: try:
if column == column_name: options = {}
options = {} for value in data_schema[column_name]["enum"]:
for value in data_schema[column]["enum"]: options[value] = value
options[value] = value return options
return options except KeyError:
return {"not_found": "not found"} return {"not_found": "not found"}
def invert_columns(columns): def invert_columns(columns):