{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Couverture et taux d'abandon par formation sanitaire\n",
    "\n",
    "*Couverture vaccinale de routine, 2024 · R*\n",
    "\n",
    "Cassion · data-analysis.cassion.dev\n",
    "\n",
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/thecassion/cassion-learning-platform/blob/main/apps/data-analysis/public/datasets/examples/routine-vaccination-coverage-2024/coverage-dropout.r.fr.ipynb)"
   ],
   "id": "cell-000"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ce que produit ce document\n",
    "\n",
    "Le même calcul d'abandon et la même logique de signalement que l'exemple Python,\n",
    "écrits avec les verbes du tidyverse.\n",
    "\n",
    "Tous les jeux de données de cette plateforme sont synthétiques. La couverture\n",
    "présentée ne décrit aucun district réel.\n",
    "\n",
    "## Mise en place"
   ],
   "id": "cell-001"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#| message: false\n",
    "library(readr)\n",
    "library(dplyr)\n",
    "library(tidyr)\n",
    "\n",
    "URL <- paste0(\n",
    "  \"https://data-analysis.cassion.dev/datasets/files/\",\n",
    "  \"vaccination-coverage-2024.v1.csv\"\n",
    ")\n",
    "\n",
    "epi <- read_csv(URL, col_types = cols(\n",
    "  facility_id = col_character(),\n",
    "  period      = col_date(),\n",
    "  .default    = col_guess()\n",
    ")) |>\n",
    "  mutate(mois = format(period, \"%Y-%m\"))\n",
    "\n",
    "glimpse(epi)"
   ],
   "id": "cell-002"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Un rapport non transmis n'est pas zéro enfant vacciné"
   ],
   "id": "cell-003"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "epi |>\n",
    "  filter(!report_submitted) |>\n",
    "  summarise(\n",
    "    lignes            = n(),\n",
    "    lignes_a_zero     = sum(doses_administered == 0),\n",
    "    formations_mois   = n_distinct(paste(facility_id, mois))\n",
    "  )"
   ],
   "id": "cell-004"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Chaque ligne non rapportée porte un zéro. Sommez sans filtrer et vous affirmez\n",
    "qu'aucun enfant de cette aire de responsabilité n'a été vacciné ce mois-là.\n",
    "\n",
    "## Le dénominateur est annuel, le rapportage est mensuel\n",
    "\n",
    "`target_population` est la cible annuelle répétée sur chaque ligne. La couverture\n",
    "mensuelle divise par ce chiffre rapporté à douze ; diviser par le chiffre annuel\n",
    "complet sous-estime la couverture d'un facteur douze."
   ],
   "id": "cell-005"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "MOIS_PAR_AN <- 12\n",
    "\n",
    "epi |>\n",
    "  filter(antigen == \"penta3\") |>\n",
    "  group_by(mois) |>\n",
    "  summarise(\n",
    "    doses          = sum(doses_administered),\n",
    "    cible_annuelle = sum(target_population),\n",
    "    completude     = round(mean(report_submitted), 3),\n",
    "    .groups = \"drop\"\n",
    "  ) |>\n",
    "  mutate(\n",
    "    denominateur_annuel_faux      = round(doses / cible_annuelle, 3),\n",
    "    denominateur_mensuel_correct  = round(doses / (cible_annuelle / MOIS_PAR_AN), 3)\n",
    "  )"
   ],
   "id": "cell-006"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## L'abandon entre penta1 et penta3\n",
    "\n",
    "L'abandon ne dépend d'aucune estimation de population : les deux termes\n",
    "proviennent du même registre, ce qui en fait un meilleur signal de programme que\n",
    "la couverture."
   ],
   "id": "cell-007"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "serie <- epi |>\n",
    "  filter(report_submitted, antigen %in% c(\"penta1\", \"penta3\")) |>\n",
    "  group_by(facility_id, antigen) |>\n",
    "  summarise(doses = sum(doses_administered), .groups = \"drop\") |>\n",
    "  pivot_wider(names_from = antigen, values_from = doses) |>\n",
    "  filter(!is.na(penta1), !is.na(penta3)) |>\n",
    "  mutate(abandon = (penta1 - penta3) / penta1) |>\n",
    "  arrange(desc(abandon))\n",
    "\n",
    "cat(\"abandon median :\", round(100 * median(serie$abandon), 1), \"%\\n\")\n",
    "head(serie, 10)"
   ],
   "id": "cell-008"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Une formation rapportant un abandon proche de zéro mérite autant de suspicion\n",
    "qu'une formation en rapportant un très élevé. Un abandon quasi nul signifie\n",
    "généralement que le penta3 a été reconstitué à partir du penta1 plutôt que compté.\n",
    "\n",
    "## Le signalement de sur-rapportage, appliqué au bon niveau"
   ],
   "id": "cell-009"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "par_mois <- epi |>\n",
    "  filter(report_submitted, antigen %in% c(\"penta1\", \"penta3\")) |>\n",
    "  select(facility_id, mois, antigen, doses_administered) |>\n",
    "  pivot_wider(names_from = antigen, values_from = doses_administered) |>\n",
    "  filter(!is.na(penta1), !is.na(penta3)) |>\n",
    "  mutate(impossible = penta3 > penta1)\n",
    "\n",
    "par_mois |>\n",
    "  group_by(facility_id) |>\n",
    "  summarise(deja_signalee = any(impossible), .groups = \"drop\") |>\n",
    "  summarise(\n",
    "    signalees  = sum(deja_signalee),\n",
    "    formations = n()\n",
    "  )"
   ],
   "id": "cell-010"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Trente-sept sur trente-huit. Un contrôle qui signale la quasi-totalité du\n",
    "district n'identifie rien : les deux doses sont administrées à des enfants\n",
    "différents à des mois différents et les décomptes n'ont aucune raison d'évoluer\n",
    "de concert, si bien que le bruit ordinaire franchit la ligne en permanence."
   ],
   "id": "cell-011"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "persistantes <- serie |> filter(abandon < 0)\n",
    "persistantes"
   ],
   "id": "cell-012"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "par_mois |>\n",
    "  filter(facility_id %in% persistantes$facility_id) |>\n",
    "  group_by(facility_id) |>\n",
    "  summarise(\n",
    "    mois_signales  = sum(impossible),\n",
    "    mois_rapportes = n(),\n",
    "    .groups = \"drop\"\n",
    "  ) |>\n",
    "  arrange(desc(mois_signales))"
   ],
   "id": "cell-013"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Six formations sur le total annuel. Voilà une liste sur laquelle un superviseur\n",
    "peut agir.\n",
    "\n",
    "## La couverture par antigène"
   ],
   "id": "cell-014"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "epi |>\n",
    "  filter(report_submitted) |>\n",
    "  group_by(antigen) |>\n",
    "  summarise(\n",
    "    couverture = round(\n",
    "      sum(doses_administered) / (sum(target_population) / MOIS_PAR_AN), 3\n",
    "    ),\n",
    "    .groups = \"drop\"\n",
    "  ) |>\n",
    "  arrange(desc(couverture))"
   ],
   "id": "cell-015"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le dénominateur ne compte que les formations ayant rapporté, ce qui maintient\n",
    "numérateur et dénominateur sur le même ensemble. C'est l'objet de l'exemple sur\n",
    "l'ajustement pour la complétude.\n",
    "\n",
    "## Ce qu'il faut rapporter\n",
    "\n",
    "La couverture avec son dénominateur énoncé, l'abandon comme signal indépendant de\n",
    "toute estimation de population, et la liste de sur-rapportage accompagnée du\n",
    "niveau d'agrégation auquel elle a été calculée."
   ],
   "id": "cell-016"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "name": "R",
   "file_extension": ".r"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
