{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Aboutissement des référencements et points de rupture du circuit\n",
    "\n",
    "*Référencements de protection, 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/protection-referrals-2024/referral-completion.r.fr.ipynb)"
   ],
   "id": "cell-000"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Avant tout code\n",
    "\n",
    "Données synthétiques modélisant des cas de protection et de VBG. Aucune personne\n",
    "réelle n'y est décrite, et ce fichier ne doit jamais servir de modèle pour\n",
    "stocker de vraies données de cas — la version sûre est un système de gestion de\n",
    "cas encadré par le consentement.\n",
    "\n",
    "La même décomposition que l'exemple Python, en dplyr, avec les enregistrements\n",
    "contradictoires et manquants traités explicitement plutôt que supprimés en\n",
    "silence.\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",
    "  \"protection-referrals-2024.v1.csv\"\n",
    ")\n",
    "\n",
    "cas <- read_csv(URL, col_types = cols(\n",
    "  case_id  = col_character(),\n",
    "  .default = col_guess()\n",
    "))\n",
    "\n",
    "glimpse(cas)"
   ],
   "id": "cell-002"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Le consentement conditionne le dénominateur"
   ],
   "id": "cell-003"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cas |>\n",
    "  summarise(\n",
    "    cas             = n(),\n",
    "    consentants     = sum(consent_to_refer),\n",
    "    taux_consentement = round(mean(consent_to_refer), 3)\n",
    "  )"
   ],
   "id": "cell-004"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "consentants <- cas |> filter(consent_to_refer)\n",
    "\n",
    "consentants |>\n",
    "  summarise(\n",
    "    denominateur = n(),\n",
    "    aboutis      = sum(referral_accepted),\n",
    "    taux         = round(mean(referral_accepted), 3)\n",
    "  )"
   ],
   "id": "cell-005"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le dénominateur de l'aboutissement, ce sont les cas ayant consenti, non\n",
    "l'ensemble des cas. Compter un cas non consentant comme un échec du circuit\n",
    "déforme à la fois la performance et la décision d'une personne : le circuit a\n",
    "fait ce qu'il devait lorsque quelqu'un a refusé.\n",
    "\n",
    "## Traiter les contradictions explicitement"
   ],
   "id": "cell-006"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cas |>\n",
    "  summarise(\n",
    "    delai_sans_acceptation = sum(!referral_accepted & !is.na(days_to_first_service)),\n",
    "    delai_sans_referencement = sum(!referral_made & !is.na(days_to_first_service)),\n",
    "    delai_sans_consentement  = sum(!consent_to_refer & !is.na(days_to_first_service)),\n",
    "    accepte_sans_delai       = sum(referral_accepted & is.na(days_to_first_service))\n",
    "  ) |>\n",
    "  pivot_longer(everything(), names_to = \"contradiction\", values_to = \"cas\")"
   ],
   "id": "cell-007"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Onze enregistrements portent un délai de service sans référencement accepté\n",
    "derrière, dont six sans aucun référencement effectué. Quarante référencements\n",
    "acceptés n'ont pas de délai consigné, ce qui signifie que **le dénominateur de la\n",
    "promptitude est plus petit que celui de l'aboutissement** — employer l'un pour\n",
    "l'autre fausse les deux."
   ],
   "id": "cell-008"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cas <- cas |>\n",
    "  mutate(contradictoire = !referral_accepted & !is.na(days_to_first_service))\n",
    "\n",
    "cat(\"signales, non supprimes :\", sum(cas$contradictoire), \"\\n\")"
   ],
   "id": "cell-009"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Signaler plutôt que supprimer compte ici. En gestion de cas, un enregistrement\n",
    "contradictoire est un problème de saisie à renvoyer au travailleur social, et le\n",
    "supprimer détruit la seule trace de l'existence du cas.\n",
    "\n",
    "## Normaliser le handicap avant de désagréger"
   ],
   "id": "cell-010"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "count(cas, disability_reported)"
   ],
   "id": "cell-011"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cas <- cas |>\n",
    "  mutate(\n",
    "    handicap = case_when(\n",
    "      tolower(trimws(disability_reported)) %in% c(\"true\", \"yes\") ~ TRUE,\n",
    "      tolower(trimws(disability_reported)) %in% c(\"false\", \"no\")  ~ FALSE,\n",
    "      TRUE ~ NA\n",
    "    )\n",
    "  )\n",
    "\n",
    "consentants <- cas |> filter(consent_to_refer)\n",
    "count(consentants, handicap)"
   ],
   "id": "cell-012"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Une zone a employé `Yes` et `No`. Laissée telle quelle, la désagrégation se\n",
    "fragmente en quatre catégories, dont deux issues de cette seule zone et trop\n",
    "petites pour être interprétées.\n",
    "\n",
    "## Où le circuit se rompt"
   ],
   "id": "cell-013"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aboutissement <- function(df, par) {\n",
    "  df |>\n",
    "    group_by(across(all_of(par))) |>\n",
    "    summarise(\n",
    "      cas     = n(),\n",
    "      aboutis = sum(referral_accepted),\n",
    "      taux    = round(mean(referral_accepted), 3),\n",
    "      .groups = \"drop\"\n",
    "    ) |>\n",
    "    arrange(taux)\n",
    "}\n",
    "\n",
    "aboutissement(consentants, \"service_requested\")"
   ],
   "id": "cell-014"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aboutissement(consentants, \"admin2\")"
   ],
   "id": "cell-015"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Le soutien aux moyens d'existence aboutit à environ 23 % contre environ 62 % pour\n",
    "la santé. Ce n'est pas de la performance de travailleur social : c'est la\n",
    "question des services qui existent et disposent de capacités. Une analyse qui\n",
    "s'arrête au 46 % global escamote tout le constat."
   ],
   "id": "cell-016"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grille <- consentants |>\n",
    "  group_by(admin2, service_requested) |>\n",
    "  summarise(cas = n(), taux = round(mean(referral_accepted), 2), .groups = \"drop\") |>\n",
    "  mutate(taux = if_else(cas >= 20, taux, NA_real_)) |>\n",
    "  select(-cas) |>\n",
    "  pivot_wider(names_from = service_requested, values_from = taux)\n",
    "\n",
    "grille"
   ],
   "id": "cell-017"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les cellules sous vingt cas sont laissées vides. Un taux sur huit cas n'est pas\n",
    "un constat, et en protection une petite cellule constitue un risque de\n",
    "divulgation autant qu'un problème statistique.\n",
    "\n",
    "## Le constat d'équité"
   ],
   "id": "cell-018"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "par_handicap <- consentants |>\n",
    "  filter(!is.na(handicap)) |>\n",
    "  aboutissement(\"handicap\")\n",
    "\n",
    "par_handicap"
   ],
   "id": "cell-019"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tbl <- table(\n",
    "  consentants$handicap[!is.na(consentants$handicap)],\n",
    "  consentants$referral_accepted[!is.na(consentants$handicap)]\n",
    ")\n",
    "chisq.test(tbl)"
   ],
   "id": "cell-020"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Les cas où un handicap est signalé aboutissent environ dix-sept points plus bas,\n",
    "et l'écart est peu susceptible d'être dû au hasard. Ce qu'il ne dit pas, c'est\n",
    "*pourquoi* — si les services sont physiquement inaccessibles, si les circuits\n",
    "supposent une mobilité que certains clients n'ont pas, ou tout autre chose. À\n",
    "cette question répondent les travailleurs sociaux, non ce tableau.\n",
    "\n",
    "## Les petites cellules sont un risque de protection"
   ],
   "id": "cell-021"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "consentants |>\n",
    "  count(admin2, case_category) |>\n",
    "  filter(n < 20)"
   ],
   "id": "cell-022"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ce contrôle ne renvoie rien ici — toutes les cellules zone par catégorie\n",
    "dépassent vingt — et ce résultat vide est précisément l'intérêt de l'exécuter.\n",
    "Une cellule de trois cas de VBG dans un tableau par district peut identifier une\n",
    "survivante pour quiconque connaît la zone : le contrôle reste donc en permanence\n",
    "dans la chaîne plutôt que d'être lancé une fois. Fixez le seuil avec l'agence de\n",
    "gestion de cas, non comme un choix de mise en forme.\n",
    "\n",
    "## Ce qu'il faut rapporter\n",
    "\n",
    "L'aboutissement sur le dénominateur conditionné par le consentement, décomposé\n",
    "assez finement pour localiser le point de rupture, les contradictions signalées et\n",
    "comptées, l'écart lié au handicap énoncé clairement — et rien à une granularité\n",
    "susceptible d'identifier une personne."
   ],
   "id": "cell-023"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "name": "R",
   "file_extension": ".r"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
