cassionAnalyse de données

Retour à la leçonLeçon 4 sur 8La même réponse deux fois

Quatre choses qui changent la réponse alors que rien n'a changé

Le même diaporama que les téléchargements, rendu sous forme de page. Lancez le diaporama pour le présenter en plein écran — les flèches ou un clic avancent d'une diapositive, Échap quitte.

Diapositives · PDFDiapositives · PowerPoint

  1. Diapositive 1 / 27

    Ce que couvre cette leçon

    • Un : l'horloge
    • Deux : la graine
    • Trois : l'ordre dans lequel les fichiers reviennent
    • Quatre : la locale
    • Le test qui attrape les quatre
    • L'habitude de la sortie déterministe
    • Rapportez-le en entier
    • La suite
    Notes du présentateur
    L'horloge, la graine, l'ordre des fichiers et la locale. Chacune produit un résultat différent depuis un code identique et des données identiques, chacune est invisible dans un diff, et cette plateforme en a rencontré trois sur quatre en production.
  2. Diapositive 2 / 27

    Un : l'horloge — En Python

    from datetime import date
    report_date = date.today()          # different every day, by design
  3. Diapositive 3 / 27

    Un : l'horloge

    • Tout ce qui lit l'heure courante fait différer chaque exécution — Un pied de page « produit le », un nom de fichier…
    • Le remède est de prendre la date des données ou d'un paramètre
    Notes du présentateur
    Tout ce qui lit l'heure courante fait différer chaque exécution. Un pied de page « produit le », un nom de fichier avec la date du jour, un filtre sur « les 30 derniers jours », une graine aléatoire dérivée du temps. Le remède est de prendre la date des données ou d'un paramètre.
  4. Diapositive 4 / 27

    Un : l'horloge — En Python

    import pandas as pd
    
    survey = pd.read_csv("data/raw/household-survey-2025.v1.csv")
    as_of = pd.to_datetime(survey["interview_date"]).max()   # from the data
  5. Diapositive 5 / 27

    Un : l'horloge — En R

    as_of <- max(as.Date(survey$interview_date))
  6. Diapositive 6 / 27

    Un : l'horloge

    • Cette plateforme s'est trompée là-dessus et l'échec est instructif — Les documents de cours et les diaporamas de leçon…
    • La date est désormais rattachée à l'artefact — Celle d'un document vient de son propre cours et de ses leçons, celle…
    Notes du présentateur
    Cette plateforme s'est trompée là-dessus et l'échec est instructif. Les documents de cours et les diaporamas de leçon prenaient à l'origine leur date de production du champ updated le plus récent de toute la bibliothèque de contenu. Déterministe — et faux quand même, parce que publier un nouveau cours réhorodatait chaque document existant et réécrivait les quatre-vingt-seize binaires de diaporama. La date est désormais rattachée à l'artefact. Celle d'un document vient de son propre cours et de ses leçons, celle d'un diaporama de sa propre leçon, celle d'un rapport de son propre projet. Une réponse fausse déterministe reste une réponse fausse, et « le diff est énorme mais correct » est la façon dont personne ne le relit.
  7. Diapositive 7 / 27

    Deux : la graine — En Python

    import numpy as np
    
    rng = np.random.default_rng(20260729)      # stated, committed, reproducible
    sample = rng.choice(households, size=200, replace=False)
  8. Diapositive 8 / 27

    Deux : la graine — En R

    set.seed(20260729)
    sample(households, 200)
  9. Diapositive 9 / 27

    Deux : la graine

    • Tout ce qui est aléatoire exige une graine et la graine a sa place dans le code — Intervalles bootstrap,…
    • Fixez-la une fois, en tête, visiblement — Une graine enfouie trois fonctions plus bas est une graine que quelqu'un…
    • Et dites-le dans la sortie — L'intervalle bootstrap du cours de régression est rapporté avec « 400 rééchantillonnages,…
    • Chaque jeu de données de cette plateforme est produit par un script à graine fixe — ce qui fait de `pnpm…
    Notes du présentateur
    Tout ce qui est aléatoire exige une graine et la graine a sa place dans le code. Intervalles bootstrap, échantillonnage aléatoire pour vérification, simulation, partitions d'apprentissage et de test, points de nuage déplacés aléatoirement. Fixez-la une fois, en tête, visiblement. Une graine enfouie trois fonctions plus bas est une graine que quelqu'un déplacera. Et dites-le dans la sortie. L'intervalle bootstrap du cours de régression est rapporté avec « 400 rééchantillonnages, graine 20260729 » exactement pour cette raison — un intervalle que personne ne peut reproduire n'est pas un intervalle. Chaque jeu de données de cette plateforme est produit par un script à graine fixe, ce qui fait de pnpm datasets:generate une étape de vérification : il réécrit les vingt CSV et git status ne signale aucun changement.
  10. Diapositive 10 / 27

    Trois : l'ordre dans lequel les fichiers reviennent — En Python

    import glob
    for path in glob.glob("data/raw/*.csv"):     # order is filesystem-dependent
        ...
  11. Diapositive 11 / 27

    Trois : l'ordre dans lequel les fichiers reviennent

    • glob et os.listdir renvoient les fichiers dans un ordre qui diffère selon les systèmes et parfois d'une exécution à…
    Notes du présentateur
    glob et os.listdir renvoient les fichiers dans un ordre qui diffère selon les systèmes et parfois d'une exécution à l'autre. Si quoi que ce soit en aval dépend de l'ordre — une concaténation, une déduplication au premier arrivé, un index de ligne — le résultat diffère.
  12. Diapositive 12 / 27

    Trois : l'ordre dans lequel les fichiers reviennent — En Python

    for path in sorted(glob.glob("data/raw/*.csv")):
        ...
  13. Diapositive 13 / 27

    Trois : l'ordre dans lequel les fichiers reviennent — En R

    for (path in sort(list.files("data/raw", full.names = TRUE))) { }
  14. Diapositive 14 / 27

    Trois : l'ordre dans lequel les fichiers reviennent

    • Triez. Toujours. Cela coûte six caractères
    • La même chose vaut pour l'ordre des dictionnaires et des groupes — groupby dans pandas trie par défaut et…
    Notes du présentateur
    Triez. Toujours. Cela coûte six caractères. La même chose vaut pour l'ordre des dictionnaires et des groupes. groupby dans pandas trie par défaut et dplyr::group_by non ; un graphique dont l'ordre des barres vient d'un groupement non trié est un graphique dont l'ordre peut changer sans que les données changent.
  15. Diapositive 15 / 27

    Quatre : la locale — En Python

    float("1,234")           # ValueError, or 1.234, depending on where you are
  16. Diapositive 16 / 27

    Quatre : la locale

    • Le séparateur décimal, le séparateur de milliers, le format de date et l'ordre de tri des caractères accentués…
    Notes du présentateur
    Le séparateur décimal, le séparateur de milliers, le format de date et l'ordre de tri des caractères accentués dépendent tous de la locale, et le public de cette plateforme travaille dans les deux conventions par définition.
  17. Diapositive 17 / 27

    Quatre : la locale — En Python

    survey = pd.read_csv(path, decimal=".", thousands=None)     # stated, not inferred
    dates = pd.to_datetime(survey["date"], format="%Y-%m-%d")   # explicit
  18. Diapositive 18 / 27

    Quatre : la locale — En R

    readr::read_csv(path, locale = locale(decimal_mark = ".", date_format = "%Y-%m-%d"))
  19. Diapositive 19 / 27

    Quatre : la locale

    • Énoncez le format plutôt que de laisser le lecteur l'inférer — pd.to_datetime sans format est une fonction qui…
    • Le tri est le plus subtil — sorted() sur des noms de communes français place Étroit après Zone sous une locale et…
    Notes du présentateur
    Énoncez le format plutôt que de laisser le lecteur l'inférer. pd.to_datetime sans format est une fonction qui devine, et elle devine différemment sur 03/04/2025 selon ce qu'il y a d'autre dans la colonne. Le tri est le plus subtil. sorted() sur des noms de communes français place Étroit après Zone sous une locale et avant Fond sous une autre, si bien que l'ordre des catégories d'un graphique devient dépendant de la machine.
  20. Diapositive 20 / 27

    Le test qui attrape les quatre — Shell

    python run.py && cp -r outputs outputs-first
    python run.py && diff -r outputs outputs-first
  21. Diapositive 21 / 27

    Le test qui attrape les quatre

    • Exécutez deux fois et comparez — Tout ce qui diffère est l'une des quatre, et le diff nomme le fichier
    • Exécutez deux fois sur des machines différentes — et vous attrapez en plus la locale et l'ordre des fichiers, ce qu'une…
    • Mettez-le dans l'intégration continue — qui est une machine propre à chaque fois, et la vérification s'exécute que…
    Notes du présentateur
    Exécutez deux fois et comparez. Tout ce qui diffère est l'une des quatre, et le diff nomme le fichier. Exécutez deux fois sur des machines différentes et vous attrapez en plus la locale et l'ordre des fichiers, ce qu'une seule machine ne peut pas faire. Mettez-le dans l'intégration continue, qui est une machine propre à chaque fois, et la vérification s'exécute que quiconque y pense ou non.
  22. Diapositive 22 / 27

    L'habitude de la sortie déterministe

    Source de bruitRemède
    Horodatages dans les métadonnées de fichierSOURCE_DATE_EPOCH, ou les retirer
    Une date de production dans un pied de pageLa prendre du contenu
    Une compression avec horodatageUne archive dont les dates d'entrée sont fixées
    L'ordre de sommation en virgule flottanteTrier avant de réduire là où cela compte
    Un identifiant aléatoire incorporéLe dériver d'une empreinte du contenu
    Notes du présentateur
    Pour tout ce qu'une compilation produit, une sortie identique octet pour octet sur entrée inchangée est l'objectif, et il est atteignable plus souvent qu'on ne le suppose.
  23. Diapositive 23 / 27

    L'habitude de la sortie déterministe

    • Cette plateforme fixe SOURCE_DATE_EPOCH pour pdfTeX et pour pandoc — parce qu'un .pptx est une archive dont les…
    • Le bénéfice est qu'un diff signifie quelque chose — Quand reconstruire ne produit aucun changement, un changement dans…
    Notes du présentateur
    Cette plateforme fixe SOURCE_DATE_EPOCH pour pdfTeX et pour pandoc, parce qu'un .pptx est une archive dont les dates d'entrée et les propriétés de document bougeraient sinon à chaque reconstruction de chaque diaporama. Le bénéfice est qu'un diff signifie quelque chose. Quand reconstruire ne produit aucun changement, un changement dans le diff est un vrai changement — et la relecture devient possible.
  24. Diapositive 24 / 27

    Rapportez-le en entier — Exemple

    Determinism
    
      All randomness is seeded: seed 20260729, set in src/config.py and reported
      with every bootstrap interval in this report.
    
      Dates are taken from the data (the latest interview date) rather than from
      the clock. No output contains a generation timestamp.
    
      File iteration is sorted. Group order is stated explicitly rather than
      inherited from the grouping library's default.
    
      CSV reading states the decimal mark and the date format rather than
      inferring them.
    
      Verified: running the pipeline twice produces byte-identical outputs, and
      CI runs it on a clean machine on every push.
  25. Diapositive 25 / 27

    Rapportez-le en entier

    • La dernière ligne est l'affirmation et les quatre au-dessus sont la façon dont elle a été obtenue — Un rapport qui…
    Notes du présentateur
    La dernière ligne est l'affirmation et les quatre au-dessus sont la façon dont elle a été obtenue. Un rapport qui affirme le déterminisme sans dire laquelle des quatre il a traitée a probablement traité la graine et aucune autre.
  26. Diapositive 26 / 27

    La suite

    • Une chaîne reproductible qui produit un rapport vaut la peine d'exister.
    Notes du présentateur
    Une chaîne reproductible qui produit un rapport vaut la peine d'exister. La leçon suivante lui en fait produire douze, depuis un seul modèle, sans une seule copie.
  27. Diapositive 27 / 27

    La suite

    Lire la leçon complète, avec le code exécutable Retour à la leçon