Top 10 acheteurs et titulaires #65
This commit is contained in:
@@ -1,36 +0,0 @@
|
|||||||
import polars as pl
|
|
||||||
from dash import html
|
|
||||||
|
|
||||||
from src.figures import DataTable
|
|
||||||
from src.utils import add_links_in_dict, format_values, setup_table_columns
|
|
||||||
|
|
||||||
|
|
||||||
def get_top_org_table(data, org_type: str, extra_columns: list):
|
|
||||||
dff = pl.DataFrame(data, strict=False, infer_schema_length=5000)
|
|
||||||
if dff.height == 0:
|
|
||||||
return html.Div()
|
|
||||||
|
|
||||||
extra_columns = [] if extra_columns is None else extra_columns
|
|
||||||
|
|
||||||
dff = dff.select(["uid", f"{org_type}_id", f"{org_type}_nom"] + extra_columns)
|
|
||||||
dff_nb = dff.group_by(
|
|
||||||
f"{org_type}_id", f"{org_type}_nom", "titulaire_distance"
|
|
||||||
).agg(pl.len().alias("Attributions"), pl.sum("montant").alias("montant"))
|
|
||||||
dff_nb = dff_nb.sort(by="montant", descending=True, nulls_last=True)
|
|
||||||
dff_nb = dff_nb.cast(pl.String)
|
|
||||||
dff_nb = dff_nb.fill_null("")
|
|
||||||
dff_nb = format_values(dff_nb)
|
|
||||||
columns, tooltip = setup_table_columns(
|
|
||||||
dff_nb, hideable=False, exclude=[f"{org_type}_id"], new_columns=["Attributions"]
|
|
||||||
)
|
|
||||||
data = dff_nb.to_dicts()
|
|
||||||
data = add_links_in_dict(data, f"{org_type}")
|
|
||||||
|
|
||||||
return DataTable(
|
|
||||||
dtid=f"top10_{org_type}",
|
|
||||||
data=data,
|
|
||||||
page_action="native",
|
|
||||||
page_size=10,
|
|
||||||
columns=columns,
|
|
||||||
tooltip_header=tooltip,
|
|
||||||
)
|
|
||||||
+58
-10
@@ -11,7 +11,14 @@ import polars as pl
|
|||||||
from dash import dash_table, dcc, html
|
from dash import dash_table, dcc, html
|
||||||
from dash_extensions.javascript import Namespace
|
from dash_extensions.javascript import Namespace
|
||||||
|
|
||||||
from src.utils import data_schema, departements_geojson, df, format_number
|
from src.utils import (
|
||||||
|
add_links,
|
||||||
|
data_schema,
|
||||||
|
departements_geojson,
|
||||||
|
df,
|
||||||
|
format_number,
|
||||||
|
setup_table_columns,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_yearly_statistics(statistics, today_str) -> html.Div:
|
def get_yearly_statistics(statistics, today_str) -> html.Div:
|
||||||
@@ -356,15 +363,15 @@ def get_duplicate_matrix() -> dcc.Graph:
|
|||||||
|
|
||||||
def get_geographic_maps(dff: pl.DataFrame) -> list | None:
|
def get_geographic_maps(dff: pl.DataFrame) -> list | None:
|
||||||
"""
|
"""
|
||||||
Génère les cartes géographiques pour la métropole et les DOM-TOM.
|
Génère les cartes géographiques pour l'hexagone et les DOM-TOM.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
regions: dict = {
|
regions: dict = {
|
||||||
"Métropole": {
|
"Hexagone": {
|
||||||
"coordinates": [46.6, 2.2],
|
"coordinates": [46.6, 2.2],
|
||||||
"zoom_leaflet": 5,
|
"zoom_leaflet": 5,
|
||||||
"zoom_chloropleth": 1,
|
"zoom_chloropleth": 1,
|
||||||
"name": "Métropole",
|
"name": "Hexagone",
|
||||||
},
|
},
|
||||||
"971": {
|
"971": {
|
||||||
"coordinates": [16.23, -61.55],
|
"coordinates": [16.23, -61.55],
|
||||||
@@ -400,7 +407,7 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
|
|||||||
|
|
||||||
def make_map_data(region_code: str) -> tuple[list, str or None]:
|
def make_map_data(region_code: str) -> tuple[list, str or None]:
|
||||||
lff: pl.LazyFrame = dff.lazy()
|
lff: pl.LazyFrame = dff.lazy()
|
||||||
if region_code == "Métropole":
|
if region_code == "Hexagone":
|
||||||
lff = lff.filter(
|
lff = lff.filter(
|
||||||
(pl.col("acheteur_departement_code").str.len_chars() == 2)
|
(pl.col("acheteur_departement_code").str.len_chars() == 2)
|
||||||
& (pl.col("titulaire_departement_code").str.len_chars() == 2)
|
& (pl.col("titulaire_departement_code").str.len_chars() == 2)
|
||||||
@@ -418,8 +425,8 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
|
|||||||
|
|
||||||
dfs = []
|
dfs = []
|
||||||
|
|
||||||
if (code == "Métropole" and nb_marches > 30000) or (
|
if (code == "Hexagone" and nb_marches > 30000) or (
|
||||||
code != "Métropole" and nb_marches > 10000
|
code != "Hexagone" and nb_marches > 10000
|
||||||
):
|
):
|
||||||
_map_type: str = "chloropleth"
|
_map_type: str = "chloropleth"
|
||||||
|
|
||||||
@@ -490,7 +497,7 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f"Map type '{map_type}' not recognised")
|
raise ValueError(f"Map type '{map_type}' not recognised")
|
||||||
|
|
||||||
lg, xl = (12, 8) if code == "Métropole" else (6, 4)
|
lg, xl = (12, 8) if code == "Hexagone" else (6, 4)
|
||||||
|
|
||||||
col = make_card(regions[code]["name"], fig=map_graph, lg=lg, xl=xl)
|
col = make_card(regions[code]["name"], fig=map_graph, lg=lg, xl=xl)
|
||||||
cols.append(col)
|
cols.append(col)
|
||||||
@@ -573,7 +580,7 @@ def make_clusters_map(region: dict) -> dl.Map:
|
|||||||
zoom=zoom,
|
zoom=zoom,
|
||||||
style={
|
style={
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
"height": "400px" if name == "Métropole" else "300px",
|
"height": "400px" if name == "Hexagone" else "300px",
|
||||||
},
|
},
|
||||||
id=f"map-{region_id}",
|
id=f"map-{region_id}",
|
||||||
)
|
)
|
||||||
@@ -626,7 +633,7 @@ def get_distance_histogram(lff: pl.LazyFrame) -> dcc.Graph:
|
|||||||
)
|
)
|
||||||
fig.update_layout(bargap=0)
|
fig.update_layout(bargap=0)
|
||||||
|
|
||||||
fig.update_layout(margin=dict(r=10))
|
fig.update_layout(margin=dict(r=10, t=10))
|
||||||
fig.update_xaxes(
|
fig.update_xaxes(
|
||||||
tickvals=[0, 1, 2, 3, 4],
|
tickvals=[0, 1, 2, 3, 4],
|
||||||
ticktext=["1", "10", "100", "1 000", "10 000"],
|
ticktext=["1", "10", "100", "1 000", "10 000"],
|
||||||
@@ -807,3 +814,44 @@ def make_column_picker(page: str):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def get_top_org_table(data, org_type: str, extra_columns: list, filters: bool = True):
|
||||||
|
if isinstance(data, pl.LazyFrame):
|
||||||
|
lff = data
|
||||||
|
else:
|
||||||
|
lff = pl.LazyFrame(data, strict=False, infer_schema_length=5000)
|
||||||
|
|
||||||
|
if org_type == "titulaire":
|
||||||
|
extra_columns.append("titulaire_typeIdentifiant")
|
||||||
|
columns = ["uid", f"{org_type}_id", f"{org_type}_nom"] + extra_columns
|
||||||
|
|
||||||
|
lff = lff.select(columns)
|
||||||
|
lff = lff.group_by([f"{org_type}_id", f"{org_type}_nom"] + extra_columns).agg(
|
||||||
|
pl.len().alias("Attributions")
|
||||||
|
)
|
||||||
|
lff = lff.sort(by="Attributions", descending=True, nulls_last=True)
|
||||||
|
lff = lff.cast(pl.String)
|
||||||
|
lff = lff.fill_null("")
|
||||||
|
|
||||||
|
dff: pl.DataFrame = lff.collect(engine="streaming")
|
||||||
|
|
||||||
|
if dff.height == 0:
|
||||||
|
return html.Div()
|
||||||
|
|
||||||
|
columns, tooltip = setup_table_columns(
|
||||||
|
dff, hideable=False, exclude=[f"{org_type}_id"], new_columns=["Attributions"]
|
||||||
|
)
|
||||||
|
dff = add_links(dff)
|
||||||
|
data = dff.to_dicts()
|
||||||
|
# data = add_links_in_dict(data, f"{org_type}")
|
||||||
|
|
||||||
|
return DataTable(
|
||||||
|
dtid=f"top10_{org_type}",
|
||||||
|
data=data,
|
||||||
|
page_action="native",
|
||||||
|
page_size=10,
|
||||||
|
columns=columns,
|
||||||
|
tooltip_header=tooltip,
|
||||||
|
filter_action="native" if filters else "none",
|
||||||
|
)
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ from dash import (
|
|||||||
register_page,
|
register_page,
|
||||||
)
|
)
|
||||||
|
|
||||||
from src.callbacks import get_top_org_table
|
|
||||||
from src.figures import (
|
from src.figures import (
|
||||||
DataTable,
|
DataTable,
|
||||||
get_distance_histogram,
|
get_distance_histogram,
|
||||||
|
get_top_org_table,
|
||||||
make_card,
|
make_card,
|
||||||
make_column_picker,
|
make_column_picker,
|
||||||
point_on_map,
|
point_on_map,
|
||||||
@@ -372,7 +372,7 @@ def get_last_marches_data(
|
|||||||
Input(component_id="acheteur_data", component_property="data"),
|
Input(component_id="acheteur_data", component_property="data"),
|
||||||
)
|
)
|
||||||
def get_top_titulaires(data):
|
def get_top_titulaires(data):
|
||||||
table = get_top_org_table(data, "titulaire", ["titulaire_distance", "montant"])
|
table = get_top_org_table(data, "titulaire", ["titulaire_distance"])
|
||||||
return make_card(fig=table, title="Top titulaires", lg=12, xl=12)
|
return make_card(fig=table, title="Top titulaires", lg=12, xl=12)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from src.figures import (
|
|||||||
get_distance_histogram,
|
get_distance_histogram,
|
||||||
get_duplicate_matrix,
|
get_duplicate_matrix,
|
||||||
get_geographic_maps,
|
get_geographic_maps,
|
||||||
|
get_top_org_table,
|
||||||
make_card,
|
make_card,
|
||||||
make_donut,
|
make_donut,
|
||||||
)
|
)
|
||||||
@@ -649,6 +650,16 @@ def udpate_dashboard_cards(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
top_acheteurs = get_top_org_table(
|
||||||
|
lff, org_type="acheteur", filters=False, extra_columns=[]
|
||||||
|
)
|
||||||
|
cards.append(make_card(title="Top acheteurs", fig=top_acheteurs, lg=12, xl=8))
|
||||||
|
|
||||||
|
top_titulaires = get_top_org_table(
|
||||||
|
lff, org_type="titulaire", filters=False, extra_columns=[]
|
||||||
|
)
|
||||||
|
cards.append(make_card(title="Top titulaires", fig=top_titulaires, lg=12, xl=8))
|
||||||
|
|
||||||
geographic_maps: list[dbc.Col] = get_geographic_maps(dff)
|
geographic_maps: list[dbc.Col] = get_geographic_maps(dff)
|
||||||
|
|
||||||
other_cards = []
|
other_cards = []
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ from dash import (
|
|||||||
register_page,
|
register_page,
|
||||||
)
|
)
|
||||||
|
|
||||||
from src.callbacks import get_top_org_table
|
|
||||||
from src.figures import (
|
from src.figures import (
|
||||||
DataTable,
|
DataTable,
|
||||||
get_distance_histogram,
|
get_distance_histogram,
|
||||||
|
get_top_org_table,
|
||||||
make_column_picker,
|
make_column_picker,
|
||||||
point_on_map,
|
point_on_map,
|
||||||
)
|
)
|
||||||
@@ -395,7 +395,7 @@ def get_last_marches_data(
|
|||||||
Input(component_id="titulaire_data", component_property="data"),
|
Input(component_id="titulaire_data", component_property="data"),
|
||||||
)
|
)
|
||||||
def get_top_acheteurs(data):
|
def get_top_acheteurs(data):
|
||||||
return get_top_org_table(data, "acheteur", ["titulaire_distance", "montant"])
|
return get_top_org_table(data, "acheteur", ["titulaire_distance"])
|
||||||
|
|
||||||
|
|
||||||
@callback(
|
@callback(
|
||||||
|
|||||||
Reference in New Issue
Block a user