Cartes avec cluster de points si > lignes #65

This commit is contained in:
Colin Maudry
2026-03-15 16:05:33 +01:00
parent 302d253e6e
commit adc8457abc
3 changed files with 55 additions and 24 deletions
+6 -2
View File
@@ -11,11 +11,15 @@ window.dash_clientside = Object.assign({}, window.dash_clientside, {
}).bindTooltip(feature.properties.tooltip); }).bindTooltip(feature.properties.tooltip);
}, },
clusterToLayer: function (feature, latlng, index, context) { clusterToLayer: function (feature, latlng, index, context) {
console.log(feature);
console.log(index);
console.log(context);
const count = feature.properties.point_count; const count = feature.properties.point_count;
const size = count < 100 ? 30 : count < 1000 ? 40 : 50; const size = count < 100 ? 30 : count < 1000 ? 40 : 50;
const color = "#333"; // Default cluster color const color = "#555"; // Default cluster color
const icon = L.divIcon({ const icon = L.divIcon({
html: `<div style="background-color: ${color}; width: ${size}px; height: ${size}px; border-radius: 50%; display: flex; align-items:center; justify-content:center; color: white; border: 2px solid white; font-weight: bold;">${count}</div>`, html: `<div style="background-color: ${context.fillColor}; width: ${size}px; height: ${size}px; border-radius: 50%; display: flex; align-items:center; justify-content:center; color: white; border: 2px solid white; font-weight: bold;">${count}</div>`,
className: "marker-cluster", className: "marker-cluster",
iconSize: L.point(size, size), iconSize: L.point(size, size),
}); });
+48 -22
View File
@@ -430,7 +430,7 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
""" """
# Si les données sont trop importantes on utilise une carte chloropleth # Si les données sont trop importantes on utilise une carte chloropleth
if dff.height > 5000: if dff.height > 50000:
return [ return [
dbc.Col( dbc.Col(
dcc.Graph( dcc.Graph(
@@ -443,21 +443,30 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
] ]
# Liste des codes départements Outre-Mer # Liste des codes départements Outre-Mer
dom_codes = ["971", "972", "973", "974", "976"] region_codes: list = ["Métropole", "971", "972", "973", "974", "976"]
dom_codes = region_codes[1:]
# Couleurs accessibles (Okabe-Ito) # Couleurs accessibles (Okabe-Ito)
color_acheteur = "#E69F00" # Orange color_acheteur = "#E69F00" # Orange
color_titulaire = "#56B4E9" # Bleu ciel color_titulaire = "#56B4E9" # Bleu ciel
regions = { regions = {}
"Métropole": dff.filter(~pl.col("acheteur_departement_code").is_in(dom_codes))
}
# Ajout des DOM s'ils ont des données # Ajout des DOM s'ils ont des données
for code in dom_codes: for code in region_codes:
dff_dom = dff.filter(pl.col("acheteur_departement_code") == code) if code == "Métropole":
if dff_dom.height > 0: dff_region = dff.filter(
name = f"Département {code}" (
~pl.col("acheteur_departement_code").is_in(dom_codes)
| (~pl.col("titulaire_departement_code").is_in(dom_codes))
)
)
else:
dff_region = dff.filter(
(pl.col("acheteur_departement_code") == code)
| (pl.col("titulaire_departement_code") == code)
)
if dff_region.height > 0:
if code == "971": if code == "971":
name = "Guadeloupe" name = "Guadeloupe"
elif code == "972": elif code == "972":
@@ -468,16 +477,21 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
name = "La Réunion" name = "La Réunion"
elif code == "976": elif code == "976":
name = "Mayotte" name = "Mayotte"
regions[name] = dff_dom elif code == "Métropole":
name = "Métropole"
else:
name = f"Département {code}"
regions[name] = dff_region
# Region centers for dash-leaflet # Region centers for dash-leaflet
region_centers = { region_centers = {
"Métropole": ([46.6, 2.2], 6), "Métropole": ([46.6, 2.2], 5),
"Guadeloupe": ([16.23, -61.55], 9), "Guadeloupe": ([16.23, -61.55], 9),
"Martinique": ([14.64, -61.02], 10), "Martinique": ([14.64, -61.02], 10),
"Guyane": ([3.93, -53.12], 7), "Guyane": ([3.93, -53.12], 7),
"La Réunion": ([-21.11, 55.53], 10), "La Réunion": ([-21.11, 55.53], 9),
"Mayotte": ([-12.82, 45.16], 11), "Mayotte": ([-12.82, 45.16], 10),
} }
# JavaScript functions for styling # JavaScript functions for styling
@@ -487,9 +501,6 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
cols = [] cols = []
for name, region_df in regions.items(): for name, region_df in regions.items():
# Prepare data for GeoJSON
marker_dicts = []
# Trace Acheteurs # Trace Acheteurs
mask_acheteur = ( mask_acheteur = (
region_df.select( region_df.select(
@@ -503,9 +514,11 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
) )
) )
acheteurs_marker_dicts = []
if mask_acheteur.height > 0: if mask_acheteur.height > 0:
for row in mask_acheteur.to_dicts(): for row in mask_acheteur.to_dicts():
marker_dicts.append( acheteurs_marker_dicts.append(
{ {
"lat": row["acheteur_latitude"], "lat": row["acheteur_latitude"],
"lon": row["acheteur_longitude"], "lon": row["acheteur_longitude"],
@@ -527,9 +540,11 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
) )
) )
titulaires_marker_dicts = []
if mask_titulaire.height > 0: if mask_titulaire.height > 0:
for row in mask_titulaire.to_dicts(): for row in mask_titulaire.to_dicts():
marker_dicts.append( titulaires_marker_dicts.append(
{ {
"lat": row["titulaire_latitude"], "lat": row["titulaire_latitude"],
"lon": row["titulaire_longitude"], "lon": row["titulaire_longitude"],
@@ -538,10 +553,11 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
} }
) )
geojson_data = dlx.dicts_to_geojson(marker_dicts) acheteurs_geojson_data = dlx.dicts_to_geojson(acheteurs_marker_dicts)
titulaires_geojson_data = dlx.dicts_to_geojson(titulaires_marker_dicts)
center, zoom = region_centers.get(name, ([46.6, 2.2], 6)) center, zoom = region_centers.get(name, ([46.6, 2.2], 6))
col_width = 12 if name == "Métropole" else 3 col_width = 6 if name == "Métropole" else 3
region_id = name.lower().replace(" ", "-") region_id = name.lower().replace(" ", "-")
cols.append( cols.append(
dbc.Col( dbc.Col(
@@ -551,12 +567,22 @@ def get_geographic_maps(dff: pl.DataFrame) -> list | None:
[ [
dl.TileLayer(), dl.TileLayer(),
dl.GeoJSON( dl.GeoJSON(
data=geojson_data, data=titulaires_geojson_data,
cluster=True, cluster=True,
zoomToBoundsOnClick=True, zoomToBoundsOnClick=True,
pointToLayer=point_to_layer, pointToLayer=point_to_layer,
clusterToLayer=cluster_to_layer, clusterToLayer=cluster_to_layer,
id=f"geojson-{region_id}", id=f"geojson-{region_id}-titulaires",
options={"fillColor": color_titulaire},
),
dl.GeoJSON(
data=acheteurs_geojson_data,
cluster=True,
zoomToBoundsOnClick=True,
pointToLayer=point_to_layer,
clusterToLayer=cluster_to_layer,
id=f"geojson-{region_id}-acheteurs",
options={"fillColor": color_acheteur},
), ),
], ],
center=center, center=center,
+1
View File
@@ -163,6 +163,7 @@ def udpate_dashboard_cards(
total_montant = df_per_uid.select(pl.col("montant").sum()).item() total_montant = df_per_uid.select(pl.col("montant").sum()).item()
nb_marches = df_per_uid.height nb_marches = df_per_uid.height
# À 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(