1

Ajouter la heatmap log des catégories et le collage des pièces imprimées

This commit is contained in:
Richard Dern 2025-12-03 17:49:46 +01:00
parent a6e89bf6ef
commit 241f48d48f
3 changed files with 43 additions and 0 deletions

View File

@ -101,6 +101,41 @@ def plot_part_categories_heatmap(categories_by_year_path: Path, destination_path
plt.close(fig)
def plot_part_categories_heatmap_log(categories_by_year_path: Path, destination_path: Path) -> None:
"""Heatmap des quantités (log1p) par catégorie et par année, en excluant les catégories vides."""
rows = load_rows(categories_by_year_path)
years = extract_years(rows)
totals: Dict[str, int] = {}
quantity_lookup = {(row["year"], row["category_id"]): int(row["quantity_non_spare"]) for row in rows}
for row in rows:
totals[row["category_id"]] = totals.get(row["category_id"], 0) + int(row["quantity_non_spare"])
categories = sorted([cat_id for cat_id, total in totals.items() if total > 0], key=lambda cat_id: -totals[cat_id])
if not categories:
return
matrix = np.zeros((len(categories), len(years)))
for i, cat_id in enumerate(categories):
for j, year in enumerate(years):
matrix[i, j] = np.log1p(quantity_lookup.get((year, cat_id), 0))
fig, ax = plt.subplots(figsize=(12, 10))
cmap = plt.get_cmap("magma")
im = ax.imshow(matrix, aspect="auto", cmap=cmap, norm=Normalize(vmin=0, vmax=matrix.max() if matrix.max() > 0 else 1))
ax.set_xticks(np.arange(len(years)))
ax.set_xticklabels(years, rotation=45, ha="right")
labels = {row["category_id"]: row["category_name"] for row in rows}
ax.set_yticks(np.arange(len(categories)))
ax.set_yticklabels([labels[cat_id] for cat_id in categories])
ax.set_xlabel("Année")
ax.set_ylabel("Catégorie de pièce")
ax.set_title("Intensité des catégories de pièces par année (log des quantités)")
cbar = fig.colorbar(ScalarMappable(norm=im.norm, cmap=cmap), ax=ax, fraction=0.025, pad=0.015)
cbar.ax.set_ylabel("log1p(quantité)", rotation=90)
ensure_parent_dir(destination_path)
fig.tight_layout()
fig.savefig(destination_path, dpi=170)
plt.close(fig)
def plot_structural_share_timeline(categories_by_year_path: Path, destination_path: Path) -> None:
"""Trace l'évolution de la part des catégories structurelles."""
rows = load_rows(categories_by_year_path)

View File

@ -4,6 +4,7 @@ from pathlib import Path
from lib.plots.part_categories import (
plot_part_categories_heatmap,
plot_part_categories_heatmap_log,
plot_structural_share_timeline,
plot_top_part_categories_area,
)
@ -13,6 +14,7 @@ CATEGORIES_BY_YEAR_PATH = Path("data/intermediate/part_categories_by_year.csv")
CATEGORIES_GLOBAL_PATH = Path("data/intermediate/part_categories_global.csv")
AREA_DESTINATION = Path("figures/step29/top_part_categories_area.png")
HEATMAP_DESTINATION = Path("figures/step29/part_categories_heatmap.png")
HEATMAP_LOG_DESTINATION = Path("figures/step29/part_categories_heatmap_log.png")
STRUCTURAL_DESTINATION = Path("figures/step29/structural_share_timeline.png")
@ -20,6 +22,7 @@ def main() -> None:
"""Génère les visuels de répartition par catégorie."""
plot_top_part_categories_area(CATEGORIES_BY_YEAR_PATH, CATEGORIES_GLOBAL_PATH, AREA_DESTINATION)
plot_part_categories_heatmap(CATEGORIES_BY_YEAR_PATH, HEATMAP_DESTINATION)
plot_part_categories_heatmap_log(CATEGORIES_BY_YEAR_PATH, HEATMAP_LOG_DESTINATION)
plot_structural_share_timeline(CATEGORIES_BY_YEAR_PATH, STRUCTURAL_DESTINATION)

View File

@ -5,6 +5,7 @@ from pathlib import Path
from lib.plots.part_categories import (
plot_part_categories_heatmap,
plot_part_categories_heatmap_log,
plot_structural_share_timeline,
plot_top_part_categories_area,
)
@ -31,15 +32,19 @@ def test_plot_part_categories_outputs_images(tmp_path: Path) -> None:
)
area_dest = tmp_path / "figures" / "step29" / "top_part_categories_area.png"
heatmap_dest = tmp_path / "figures" / "step29" / "part_categories_heatmap.png"
heatmap_log_dest = tmp_path / "figures" / "step29" / "part_categories_heatmap_log.png"
structural_dest = tmp_path / "figures" / "step29" / "structural_share_timeline.png"
plot_top_part_categories_area(by_year, by_global, area_dest, top_n=2)
plot_part_categories_heatmap(by_year, heatmap_dest)
plot_part_categories_heatmap_log(by_year, heatmap_log_dest)
plot_structural_share_timeline(by_year, structural_dest)
assert area_dest.exists()
assert heatmap_dest.exists()
assert heatmap_log_dest.exists()
assert structural_dest.exists()
assert area_dest.stat().st_size > 0
assert heatmap_dest.stat().st_size > 0
assert heatmap_log_dest.stat().st_size > 0
assert structural_dest.stat().st_size > 0