cassionAnalyse de données

Retour à la leçonLeçon 6 sur 8La cohorte

Un taux de survie qu'il ne faut pas publier

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 / 30

    Ce que couvre cette leçon

    • Le calcul vers lequel tout le monde se tourne
    • Pourquoi il est faux
    • Que calculer à la place
    • Qui part
    • Les données manquantes ne le sont pas au hasard
    • Rapportez-le comme un profil de risque
    • La suite
    Notes du présentateur
    Chaînez les taux de passage d'une année et 19,3 % des enfants atteignent la dernière année. Comptez les redoublants comme retenus et cela fait 40,3 %. Les deux viennent du même fichier, et aucun n'est un taux d'achèvement.
  2. Diapositive 2 / 30

    Le calcul vers lequel tout le monde se tourne — En Python (suite)

    import pandas as pd
    
    enrolment = pd.read_csv("school-enrolment-2024.v1.csv")
    clean = enrolment[enrolment["age_years"] <= 20]
    cohort = clean[clean["school_year"] == 2023]
    
    survival, cumulative = {}, 1.0
    for grade in range(1, 7):
        grade_rows = cohort[cohort["grade"] == grade]
        promoted = grade_rows["end_of_year_status"].isin(
            ["promoted", "completed-final-grade"]).mean()
        survival[grade] = cumulative
        cumulative *= promoted
        print(f"grade {grade}: promotion {promoted:.1%}, "
              f"survival to here {survival[grade]:.1%}")
    
    Notes du présentateur
    Vous avez les taux de passage par année pour une année scolaire. Chaînez-les et vous obtenez la survie jusqu'à la dernière année — la mesure d'achèvement de type ODD — sans attendre six ans.
  3. Diapositive 3 / 30

    Le calcul vers lequel tout le monde se tourne — En Python (suite)

    print(f"\nsurvival to grade 6 entry: {cumulative:.1%}")
  4. Diapositive 4 / 30

    Le calcul vers lequel tout le monde se tourne — En R

    library(dplyr)
    
    cohort |>
      filter(between(grade, 1, 6)) |>
      summarise(promotion = mean(end_of_year_status %in%
                  c("promoted", "completed-final-grade")), .by = grade) |>
      arrange(grade) |>
      mutate(survival = cumprod(lag(promotion, default = 1)))
  5. Diapositive 5 / 30

    Le calcul vers lequel tout le monde se tourne

    AnnéePassageSurvie cumulée
    189,3 %100,0 %
    283,0 %89,3 %
    371,7 %74,1 %
    476,2 %53,1 %
    570,9 %40,5 %
    667,3 %28,7 %
    ——19,3 %
  6. Diapositive 6 / 30

    Le calcul vers lequel tout le monde se tourne

    • 19,3 % des enfants entrant en première année atteignent la fin du primaire — C'est un nombre frappant, c'est ce que la…
    Notes du présentateur
    19,3 % des enfants entrant en première année atteignent la fin du primaire. C'est un nombre frappant, c'est ce que la méthode produit, et il ne doit pas quitter votre écran.
  7. Diapositive 7 / 30

    Pourquoi il est faux

    • Les redoublants sont comptés comme des échecs — Un enfant qui redouble la deuxième année n'est pas déscolarisé — il est…
    Notes du présentateur
    C'est une cohorte reconstruite : elle suppose que le taux de passage de cinquième année observé cette année est celui que les enfants aujourd'hui en première année connaîtront dans quatre ans. Quatre choses cassent cette hypothèse, et ici elles la cassent toutes dans le même sens. Les redoublants sont comptés comme des échecs. Un enfant qui redouble la deuxième année n'est pas déscolarisé — il est de nouveau en deuxième année. La chaîne traite le non-passage comme une sortie, si bien que 10,1 % de redoublement se composent six fois en une perte apparente énorme.
  8. Diapositive 8 / 30

    Pourquoi il est faux — En Python

    promotion_or_repeat = cohort[cohort["grade"].between(1, 6)].groupby("grade")[
        "end_of_year_status"].apply(
        lambda s: s.isin(["promoted", "completed-final-grade", "repeated"]).mean())
    
    still_enrolled = 1.0
    for grade, rate in promotion_or_repeat.items():
        still_enrolled *= rate
    print(f"survival counting repeaters as retained: {still_enrolled:.1%}")
  9. Diapositive 9 / 30

    Pourquoi il est faux — En R

    # Retention, not promotion, is what a survival rate needs.
  10. Diapositive 10 / 30

    Pourquoi il est faux

    • Les transferts sont eux aussi comptés comme des échecs — 2,9 % sont partis dans une autre école et la chaîne les lit…
    • Une seule année est prise pour six — Le taux de passage de sixième observé en 2023 appartient à des enfants entrés en…
    • Les effectifs par année ne forment pas une cohorte — La première année compte 149 élèves et la sixième 110, et une…
    Notes du présentateur
    Les transferts sont eux aussi comptés comme des échecs. 2,9 % sont partis dans une autre école et la chaîne les lit comme quittant l'éducation. Une seule année est prise pour six. Le taux de passage de sixième observé en 2023 appartient à des enfants entrés en 2018, dans d'autres conditions. Les effectifs par année ne forment pas une cohorte. La première année compte 149 élèves et la sixième 110, et une partie de cet écart est une attrition réelle tandis qu'une autre est une population qui change — une cohorte de naissances plus large arrivant en première année fait ressembler la pyramide à de l'abandon.
  11. Diapositive 11 / 30

    Que calculer à la place

    • La rétention, non le passage — s'il faut employer une seule année
    Notes du présentateur
    La rétention, non le passage, s'il faut employer une seule année. Comptez comme retenus les enfants encore scolarisés — passés ou redoublants.
  12. Diapositive 12 / 30

    Que calculer à la place — En Python

    def chained(statuses):
        rate, product = {}, 1.0
        for grade in range(1, 7):
            rows = cohort[cohort["grade"] == grade]["end_of_year_status"]
            product *= rows.isin(statuses).mean()
            rate[grade] = product
        return product
    
    promotion_only = chained(["promoted", "completed-final-grade"])
    retained = chained(["promoted", "completed-final-grade", "repeated"])
    print(f"chained promotion: {promotion_only:.1%}")
    print(f"chained retention: {retained:.1%}")
  13. Diapositive 13 / 30

    Que calculer à la place — En R

    # Same chain, different numerator. The gap is repetition compounding.
  14. Diapositive 14 / 30

    Que calculer à la place

    • 19,3 % contre 40,3 % — Plus de vingt points de la perte apparente étaient du redoublement lu comme une sortie, et le…
    • Suivez de vrais élèves quand vous le pouvez — Ce registre a deux années et les mêmes identifiants, si bien qu'une…
    Notes du présentateur
    19,3 % contre 40,3 %. Plus de vingt points de la perte apparente étaient du redoublement lu comme une sortie, et le chiffre de rétention est le plus proche de quelque chose de signifiant — sans être pour autant un taux d'achèvement. Suivez de vrais élèves quand vous le pouvez. Ce registre a deux années et les mêmes identifiants, si bien qu'une transition d'un an est directement observable plutôt que supposée.
  15. Diapositive 15 / 30

    Que calculer à la place — En Python

    years = clean.pivot_table(index="student_id", columns="school_year",
                              values="grade", aggfunc="first")
    both = years.dropna()
    print(f"students observed in both years: {len(both)}")
    print(f"  advanced a grade: {(both[2024] > both[2023]).mean():.1%}")
    print(f"  same grade:       {(both[2024] == both[2023]).mean():.1%}")
  16. Diapositive 16 / 30

    Que calculer à la place

    • 1 103 élèves figurent dans les deux années : 88,5 % ont avancé d'une année et 11,5 % sont deux fois dans la même —…
    Notes du présentateur
    1 103 élèves figurent dans les deux années : 88,5 % ont avancé d'une année et 11,5 % sont deux fois dans la même. C'est une transition mesurée et non supposée, et c'est le nombre à mettre dans un rapport.
  17. Diapositive 17 / 30

    Que calculer à la place — En R

    enrolment |>
      select(student_id, school_year, grade) |>
      tidyr::pivot_wider(names_from = school_year, values_from = grade) |>
      filter(!is.na(`2023`), !is.na(`2024`))
  18. Diapositive 18 / 30

    Que calculer à la place

    • Une transition d'un an observée sur de vrais élèves vaut mieux qu'une chaîne de six ans assemblée à partir des taux…
    Notes du présentateur
    Une transition d'un an observée sur de vrais élèves vaut mieux qu'une chaîne de six ans assemblée à partir des taux d'une seule année, même si elle répond à une question plus petite. La question plus petite est défendable.
  19. Diapositive 19 / 30

    Qui part — En Python

    year23 = cohort.assign(
        over_age=cohort["age_years"] > cohort["grade"] + 5,
        dropped=cohort["end_of_year_status"].eq("dropped-out"),
    )
    for column in ("over_age", "disability_reported", "displacement_status", "sex"):
        table = year23.groupby(column, dropna=False)["dropped"].agg(["mean", "size"])
        print((table * [100, 1]).round(1), "\n")
    Notes du présentateur
    La désagrégation qui, elle, donne quelque chose, contrairement aux ventilations du retard d'âge de la leçon 2.
  20. Diapositive 20 / 30

    Qui part — En R

    cohort |>
      mutate(dropped = end_of_year_status == "dropped-out") |>
      summarise(dropout = mean(dropped), n = n(), .by = displacement_status)
  21. Diapositive 21 / 30

    Qui part

    VentilationAbandonn
    En retard d'âge19,5 %478
    À l'âge attendu4,8 %814
    Retournés19,7 %71
    Handicap signalé17,9 %112
    Déplacés internes14,7 %163
    Communauté d'accueil11,6 %95
    Résidents8,6 %940
    Garçons10,4 %634

    …

  22. Diapositive 22 / 30

    Qui part

    • Le retard d'âge est le prédicteur le plus fort et le groupe le plus grand — Le handicap et le déplacement doublent à…
    • Le sexe ne montre rien — 10,4 % contre 10,0 % sur 634 et 658 élèves
    Notes du présentateur
    Le retard d'âge est le prédicteur le plus fort et le groupe le plus grand. Le handicap et le déplacement doublent à peu près le taux sur des dénominateurs plus petits. Le sexe ne montre rien — 10,4 % contre 10,0 % sur 634 et 658 élèves. C'est un résultat qui mérite d'être énoncé, car un écart de genre dans l'abandon est le constat qu'un programme éducatif s'attend le plus à voir et ce registre n'en contient pas.
  23. Diapositive 23 / 30

    Les données manquantes ne le sont pas au hasard — En Python

    print(year23["displacement_status"].isna().sum(), "students with no status")
    print(year23.loc[year23["displacement_status"].isna(), "dropped"].mean())
  24. Diapositive 24 / 30

    Les données manquantes ne le sont pas au hasard — En R

    cohort |> filter(is.na(displacement_status)) |> nrow()
  25. Diapositive 25 / 30

    Les données manquantes ne le sont pas au hasard

    • Soyez précis sur ce que cela biaise et ne biaise pas — Les vides sont retirés à peu près au hasard à l'intérieur de…
    • le taux d'abandon des déplacés internes et des retournés n'est pas biaisé — 14,7 % et 19,7 % sont les bons nombres…
    • leurs effectifs et leur part de population sont sous-estimés d'environ un dixième. 234 élèves sont enregistrés…
    Notes du présentateur
    Le statut de déplacement est vide pour 42 élèves du registre, dont 23 dans la cohorte 2023. Les vides proviennent entièrement de ménages déplacés et retournés — c'est le champ qu'un enquêteur saute quand une famille vient d'arriver. Soyez précis sur ce que cela biaise et ne biaise pas. Les vides sont retirés à peu près au hasard à l'intérieur de ces deux catégories, donc : Donc « les enfants déplacés abandonnent à 14,7 % » est défendable et « les enfants déplacés représentent 18 % des effectifs » ne l'est pas. Un motif de valeurs manquantes peut biaiser un effectif sans biaiser un taux, et savoir sur lequel repose votre phrase décide si le motif compte. L'abandon observé parmi les vides eux-mêmes vaut 8,7 % sur 23 élèves, ce qui est trop peu pour en lire quoi que ce soit et ne doit pas être rapporté comme une catégorie.
  26. Diapositive 26 / 30

    Rapportez-le comme un profil de risque — Exemple (suite)

    Dropout, 2023 cohort, 1,292 students
    
      Overall                      10.2%
    
      Over-age for grade           19.5%   478 students
      In-age                        4.8%   814
    
      Returnee                     19.7%    71 students
      Disability reported          17.9%   112
      Internally displaced         14.7%   163
      Resident                      8.6%   940
    
      No meaningful difference by sex: 10.4% boys, 10.0% girls.
    
      42 students have no displacement status, all drawn from displaced and
      returnee households. The rates above are unbiased for those groups; their
  27. Diapositive 27 / 30

    Rapportez-le comme un profil de risque — Exemple (suite)

      counts are understated by about a tenth.
    
      Not reported: survival to the final grade. A reconstructed cohort from a
      single year gives 19.3% on promotion and 40.3% on retention, neither of
      which is a completion rate. A true cohort needs six years of the register
      or a household survey. The measured one-year transition is 88.5%.
  28. Diapositive 28 / 30

    Rapportez-le comme un profil de risque

    • « Non rapporté, et pourquoi » est la ligne la plus utile de ce bloc — Quelqu'un demandera un taux d'achèvement, et la…
    Notes du présentateur
    « Non rapporté, et pourquoi » est la ligne la plus utile de ce bloc. Quelqu'un demandera un taux d'achèvement, et la réponse en est une vraie : pas à partir de ceci, à partir d'une enquête ménage, et voici ce que ceci peut dire à la place.
  29. Diapositive 29 / 30

    La suite

    • L'inscription, la présence et la rétention disent si les enfants sont à l'école.
    Notes du présentateur
    L'inscription, la présence et la rétention disent si les enfants sont à l'école. Aucune ne dit s'ils apprennent, et la dernière unité porte sur l'instrument qui le dit — où deux passations se révèlent non comparables.
  30. Diapositive 30 / 30

    La suite

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