Remodelage et tableaux croisés dynamiques
Le remodelage change la disposition des valeurs dans une table. Dans l’exemple ci-dessous, la table longue contient une ligne par date et par indicateur ; la table large contient une ligne par date et une colonne par indicateur. Ce que représente une ligne constitue sa granularité. pivot réorganise les valeurs sans les agréger, tandis que pivot_table combine les observations selon une fonction, par exemple une somme. Définissez ce que chaque ligne du résultat doit représenter avant de choisir l’opération.
Choisir l'opération
import pandas as pd
observations = pd.DataFrame({
"date": ["2026-01-01", "2026-01-01", "2026-01-02"],
"metric": ["visits", "sales", "visits"], "value": [10, 2, 20],
})
wide = observations.pivot(index="date", columns="metric", values="value")
sales = pd.DataFrame({
"region": ["east", "east", "west"], "product": ["A", "A", "B"], "revenue": [10, 20, 5]
})
summary = sales.pivot_table(
index="region",
columns="product",
values="revenue",
aggfunc="sum",
fill_value=0,
margins=True,
observed=True,
)
pivot échoue si une paire index/colonne possède plusieurs valeurs. C'est un contrôle utile de granularité.
N'utilisez pivot_table que si l'agrégation est intentionnelle, et choisissez-la explicitement.
Revenir au format long
long = wide.reset_index().melt(
id_vars="date",
var_name="metric",
value_name="value",
)
Après remodelage, vérifiez le nombre de lignes ou l'unicité des clés et distinguez les combinaisons
structurellement absentes des observations manquantes. fill_value=0 n'est valide que si
« aucune observation représentée » signifie réellement zéro.
Ce qui reste récupérable
Ici, wide a la forme (2, 2) : visits vaut 10 puis 20, sales vaut 2 puis manquant. melt produit quatre lignes, dont la combinaison sales absente du 2 janvier. Ce n’est donc pas un aller-retour exact vers les trois lignes initiales sans traitement de cette absence structurelle. Ne supprimez pas aveuglément les valeurs manquantes si certaines étaient réellement observées.
L’API de tableau croisé agrège la table sales distincte : east/A vaut 30, west/B vaut 5 et le total summary.loc["All", "All"] vaut 35. L’agrégation perd les observations individuelles 10 et 20 ; melt ne les restaure pas. margins=True recalcule les totaux avec la fonction d’agrégation : une marge moyenne n’est généralement pas la moyenne non pondérée des moyennes affichées. Précisez observed et dropna si les catégories ou les clés manquantes affectent la table voulue.