cassionAnalyse de données

Retour à la leçonLeçon 4 sur 8Inscrit n'est pas présent

Une grève qui ressemble à une urgence

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

    Ce que couvre cette leçon

    • Les lignes qui n'y sont pas
    • Ce qui arrive si on ne regarde pas
    • La règle
    • Quand une fermeture est le constat
    • La forme générale
    • La suite
    Notes du présentateur
    SCH07 est à 88,2 % de présence et SCH18 à 85,2 %. Construisez le registre comme un calendrier complet et comptez chaque jour manquant comme une absence, et ils affichent 66,1 % et 63,9 % — les pires écoles du district, sur quinze jours où personne n'était censé être là.
  2. Diapositive 2 / 20

    Les lignes qui n'y sont pas — En Python

    import pandas as pd
    
    attendance = pd.read_csv("school-attendance-2024.v1.csv")
    roster = pd.read_csv("school-roster-2024.v1.csv")
    
    joined = attendance.merge(roster[["student_id", "school_id"]], on="student_id")
    calendar = sorted(attendance["attendance_date"].unique())
    
    days_per_school = joined.groupby("school_id")["attendance_date"].nunique()
    print(f"school days in the calendar: {len(calendar)}")
    print(days_per_school.sort_values().head())
    Notes du présentateur
    Les lignes de présence n'existent que pour les jours où une école était ouverte. Une date sans ligne est une fermeture, non une absence, et rien dans le fichier ne dit laquelle.
  3. Diapositive 3 / 20

    Les lignes qui n'y sont pas — En R

    library(dplyr)
    
    attendance |>
      left_join(roster, by = "student_id") |>
      summarise(days = n_distinct(attendance_date), .by = school_id) |>
      arrange(days)
  4. Diapositive 4 / 20

    Les lignes qui n'y sont pas

    • Vingt-deux écoles ont les soixante jours. SCH07 et SCH18 en ont quarante-cinq
    Notes du présentateur
    Vingt-deux écoles ont les soixante jours. SCH07 et SCH18 en ont quarante-cinq.
  5. Diapositive 5 / 20

    Les lignes qui n'y sont pas — En Python

    missing = {
        school: sorted(set(calendar) - set(group["attendance_date"]))
        for school, group in joined.groupby("school_id")
    }
    for school, dates in missing.items():
        if dates:
            print(f"{school}: {len(dates)} days, {dates[0]} to {dates[-1]}")
  6. Diapositive 6 / 20

    Les lignes qui n'y sont pas — En R

    # Which dates, not just how many. The pattern is the diagnosis.
  7. Diapositive 7 / 20

    Les lignes qui n'y sont pas

    • Aux deux il manque exactement du 11 au 29 mars — et les mêmes quinze jours
    • Des jours manquants consécutifs dans plusieurs écoles sont une fermeture jusqu'à preuve du contraire — Des jours…
    Notes du présentateur
    Aux deux il manque exactement du 11 au 29 mars, et les mêmes quinze jours. Ce ne sont pas deux écoles avec un problème d'assiduité ; c'est un seul événement. Des jours manquants consécutifs dans plusieurs écoles sont une fermeture jusqu'à preuve du contraire. Des jours manquants épars dans une seule école sont un problème d'enregistrement. La forme dit laquelle, et la regarder prend une ligne.
  8. Diapositive 8 / 20

    Ce qui arrive si on ne regarde pas — En Python

    def attendance_rate(school, missing_counts_as_absent):
        students = roster.loc[roster["school_id"] == school, "student_id"]
        marks = attendance[attendance["student_id"].isin(students)]
        present = marks["present"].isin(["true", "Y"]).sum()
        if missing_counts_as_absent:
            denominator = len(students) * len(calendar)
        else:
            denominator = marks["present"].isin(["true", "Y", "false", "N"]).sum()
        return present / denominator
    
    for school in ("SCH07", "SCH18", "SCH01"):
        observed = attendance_rate(school, False)
        filled = attendance_rate(school, True)
        print(f"{school}: observed {observed:.1%}, grid-filled {filled:.1%}")
    Notes du présentateur
    La façon naturelle de bâtir un tableau de présence est de construire la grille complète élèves × jours d'école et d'y reporter les pointages. C'est aussi la façon de transformer une grève en crise.
  9. Diapositive 9 / 20

    Ce qui arrive si on ne regarde pas — En R

    # Two denominators: marks made, and student-days in the calendar.
  10. Diapositive 10 / 20

    Ce qui arrive si on ne regarde pas

    ÉcoleSur les pointages faitsSur une grille complète
    SCH0788,2 %66,1 %
    SCH1885,2 %63,9 %
    SCH0191,3 %91,3 %
  11. Diapositive 11 / 20

    Ce qui arrive si on ne regarde pas

    • Vingt-deux points, inventés — Sur les chiffres de la grille complète, SCH07 et SCH18 sont de loin les deux pires écoles…
    • L'école non touchée est inchangée — ce qui rend l'erreur si difficile à attraper : le tableau a l'air correct,…
    Notes du présentateur
    Vingt-deux points, inventés. Sur les chiffres de la grille complète, SCH07 et SCH18 sont de loin les deux pires écoles du district, et un programme lisant ce tableau enverrait une réponse d'urgence contre l'abandon à deux écoles dont les enfants sont venus normalement chaque jour où on le leur a demandé. L'école non touchée est inchangée, ce qui rend l'erreur si difficile à attraper : le tableau a l'air correct, l'essentiel l'est, et les deux lignes fausses sont les deux sur lesquelles on agit.
  12. Diapositive 12 / 20

    La règle

    • Construisez le dénominateur à partir des jours d'ouverture de l'école, non du calendrier
    Notes du présentateur
    Construisez le dénominateur à partir des jours d'ouverture de l'école, non du calendrier.
  13. Diapositive 13 / 20

    La règle — En Python

    open_days = joined.groupby("school_id")["attendance_date"].nunique()
    enrolled = roster.groupby("school_id")["student_id"].nunique()
    expected = (open_days * enrolled).rename("student_days_expected")
    
    actual = joined.groupby("school_id").size().rename("marks_made")
    coverage = (actual / expected).rename("mark_coverage")
    print(pd.concat([expected, actual, coverage.round(3)], axis=1).head())
  14. Diapositive 14 / 20

    La règle — En R

    # Expected student-days uses each school's own open days.
    Notes du présentateur
    Cela donne un second nombre utile : la couverture de pointage, la part des jours-élèves attendus qui portent effectivement un pointage. Une école à 100 % de présence et 60 % de couverture de pointage n'est pas une école à bonne assiduité.
  15. Diapositive 15 / 20

    Quand une fermeture est le constat — Exemple

    Attendance, February to April 2024
    
      Average daily attendance, all schools    88.4%   on marks made
      SCH07                                    88.2%
      SCH18                                    85.2%
    
      SCH07 and SCH18 were closed for the fifteen school days from 11 to 29
      March, a quarter of the term. Their attendance figures are computed on the
      45 days they were open and are comparable with other schools; their
      instructional time is not.
    
      Counting the closure days as absences would report these two schools at
      66.1% and 63.9% and rank them worst in the district.
    Notes du présentateur
    Quinze jours d'école font un quart du trimestre. La fermeture pèse plus que tout chiffre de présence de ce fichier, et une analyse qui exclut correctement ces jours puis n'en dit rien a retiré la plus grande chose qui se soit produite.
  16. Diapositive 16 / 20

    Quand une fermeture est le constat

    • Rapportez la fermeture en jours d'enseignement perdus, séparément de la présence — Les deux répondent à des questions…
    Notes du présentateur
    Rapportez la fermeture en jours d'enseignement perdus, séparément de la présence. Les deux répondent à des questions différentes : la présence porte sur la venue des enfants, les jours d'enseignement sur le fait que l'école a eu lieu.
  17. Diapositive 17 / 20

    La forme générale

    CoursLa chose absenteCe à quoi cela ressemblait
    Données de routine et DHIS2Une formation qui n'a pas rapportéUn district à couverture en baisse
    Analyse EAHUne tournée que personne n'a conduiteUn district à fonctionnalité en hausse
    ÉducationUn jour où l'école était ferméeDeux écoles en urgence d'abandon
    Notes du présentateur
    C'est la troisième fois que cette plateforme rencontre le même défaut dans un fichier différent.
  18. Diapositive 18 / 20

    La forme générale

    • Dans les trois cas, l'absence n'est pas une valeur et rien dans le fichier ne l'annonce — L'habitude qui attrape les…
    Notes du présentateur
    Dans les trois cas, l'absence n'est pas une valeur et rien dans le fichier ne l'annonce. L'habitude qui attrape les trois est la même : avant de calculer un taux, construisez ce que le dénominateur devrait être à partir d'autre chose que des lignes dont vous disposez, et comparez.
  19. Diapositive 19 / 20

    La suite

    • La présence décrit un trimestre.
    Notes du présentateur
    La présence décrit un trimestre. Savoir si un enfant est encore scolarisé l'année suivante est une autre question, et l'unité suivante suit la cohorte 2023 à travers passage, redoublement et abandon pour y répondre.
  20. Diapositive 20 / 20

    La suite

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