: 1h30 à 2hPFINAL

🏥 Projet Final — Niveau Débutant : Audit des infrastructures sanitaires de Côte d'Ivoire

Bootcamp Data Analyst — From Zero to Hero | Niveau Débutant · Projet Final


🎯 Ce que ce projet valide

  • Acte I — Lire et interpréter un jeu de données réel
  • Acte II — Nettoyer et structurer des données dans Excel/Google Sheets, tableau croisé dynamique
  • Acte III — Écrire une requête SQL (agrégation, filtre, tri)
  • Acte IV — Reproduire la même analyse en Python (pandas) et R (dplyr)
  • Compétence transverse — Trouver et citer une source d'open data officielle, obtenir le même résultat avec 4 outils différents

⏱️ Durée estimée : 1h30 à 2h 🛠️ Outils : Excel ou Google Sheets · SQLite (sqliteonline.com) · Python · R 📌 Prérequis : Niveau Débutant terminé — Modules 01 à 12 + Mini-Projets A et B



1. Contexte — Le brief

Tu viens d'être recruté(e) comme Data Analyst junior à l'Observatoire Ivoirien de la Santé (OIS), un think tank indépendant basé à Abidjan qui produit des analyses pour éclairer les politiques de santé publique en Côte d'Ivoire.

Ta responsable, Dr. Ahou Koffi, Directrice des études, t'envoie ce message :

« Bonjour,

Le Ministère de la Santé a publié en open data les statistiques des infrastructures sanitaires du pays entre 2009 et 2015 — cabinets dentaires, hôpitaux, blocs opératoires, laboratoires...

Pour notre prochaine réunion, j'ai besoin de savoir quelles régions sont les mieux dotées en infrastructures de santé. On doit pouvoir refaire ce calcul avec n'importe quel outil selon qui est disponible dans l'équipe — assure-toi que ton résultat tienne la route en Excel, en SQL et en Python/R.

Ce sont de vraies données gouvernementales — attends-toi à ce qu'elles soient moins propres qu'un jeu de données d'exercice. C'est aussi ça, le métier.

Merci, et bienvenue dans l'équipe ! — Dr. Koffi »



2. Les données — un vrai jeu de données ouvertes

Contrairement aux modules précédents, tu ne vas pas copier-coller un tableau depuis ce notebook : tu vas télécharger toi-même le fichier officiel, exactement comme le ferait un·e Data Analyst en poste.

2.1 Télécharger le fichier

  1. Va sur data.gouv.ci — le portail officiel d'open data de la Côte d'Ivoire.
  2. Vérifie que tu es bien sur le jeu de données « Données sur l'hôpital ivoirien de 2009 à 2015 », publié par la Direction de la Prospective, de la Planification, de l'Évaluation et de l'Information Sanitaire (DPPEIS) — Ministère de la Santé et de l'Hygiène Publique — sous Licence Ouverte.
  3. Repère le bouton de téléchargement sur la page et récupère le fichier au format .xlsx.
  4. Vérifie que ton fichier contient bien environ 4 442 lignes sur une seule feuille. Si tu obtiens quelque chose de très différent, tu n'es pas sur la bonne ressource.

💡 Pourquoi cette étape compte : savoir localiser, vérifier et citer une source de données officielle est une compétence à part entière du métier. En conditions réelles, personne ne te donnera un CSV pré-nettoyé avec un joli nom de colonne.

2.2 Structure du fichier

Le fichier contient une seule feuille avec 6 colonnes :

Colonne Contenu Exemple
ANNEE Année de la mesure 2009, 2012, 2013, 2014, 2015
REGIONS Région administrative AGNEBY, GBEKE, ABIDJAN 2...
DISTRICTS/VILLES/COMMUNES Ville ou commune ADZOPE, AGBOVILLE...
CATEGORIES Type d'infrastructure ou de personnel CHR, Cabinets dentaires, Médecins...
SOUS-CATEGORIES Nature de la mesure Lits, Plateau Technique, INFRASTRUCTURE PUBLIQUE
EFFECTIFS La valeur mesurée 28, 0, 15...

2.3 Glossaire des sigles de santé publique

La colonne CATEGORIES utilise des sigles du secteur de la santé ivoirien. Avant d'explorer le fichier, voici ce qu'ils signifient :

Sigle Signification
CHR Centre Hospitalier Régional
CHU Centre Hospitalier Universitaire
HG Hôpital Général
ESPC Établissement Sanitaire de Premier Contact
MAT Maternité

C'est maintenant à toi d'explorer le reste du fichier : combien de valeurs distinctes contient CATEGORIES ? Quelles régions et quelles années sont couvertes ? Y a-t-il des valeurs manquantes ?



🎯 L'exercice

Une seule mission, à mener dans chacun des 4 outils :

Calcule, pour l'année 2015, le nombre total d'infrastructures de santé (somme des 7 catégories : Cabinets dentaires, Etablissements Sanitaires de Premier Contact (ESPC), CHR, Laboratoires d'analyse, Blocs opératoires, Services de radiologie, Hôpitaux Généraux (HG)) pour chaque région, puis identifie les 5 régions les mieux dotées.

Va plus loin que le total : regarde aussi le détail par catégorie pour les régions en tête et en queue de classement. Une région peut sembler bien dotée au total tout en manquant cruellement d'un type d'infrastructure précis (pas de bloc opératoire, pas de CHR...) — c'est ce genre de nuance qu'un∙e décideur∙se en santé publique veut voir.

Fais-le une première fois en Excel/Sheets (avec un graphique), puis reproduis exactement la même analyse en SQL, en Python et en R (avec un graphique dans ces deux derniers). À chaque étape, compare ton résultat à celui obtenu avec l'outil précédent — ils doivent être identiques.



📊 En Excel / Google Sheets

Compétences réactivées : M03-M05

  1. Ouvre le fichier téléchargé, convertis la plage en tableau structuré (Ctrl + T).
  2. Nettoie la colonne CATEGORIES (regarde s'il n'y a pas un espace en trop quelque part).
  3. Construis un TCD : Lignes = REGIONS, Filtre = ANNEE (2015) et CATEGORIES (les 7 catégories d'infrastructures), Valeurs = somme de EFFECTIFS.
  4. Trie le résultat par ordre décroissant.
  5. Ajoute CATEGORIES en Colonnes du même TCD (en plus du Filtre) pour voir la répartition par catégorie de chaque région.
  6. Construis un graphique en barres (horizontales) du classement, et un graphique en barres empilées pour la répartition par catégorie des 5 premières et 5 dernières régions.
👉 Correction

Nettoyage : =SUPPRESPACE([@CATEGORIES]) pour retirer les espaces parasites avant de filtrer ou de construire le TCD.

TCD : Insertion → Tableau croisé dynamique, REGIONS en Lignes, EFFECTIFS (Somme) en Valeurs, ANNEE en Filtre. Trie via clic droit sur la colonne des totaux → Trier → Décroissant. Ajoute CATEGORIES en Colonnes pour voir le détail.

Graphiques : sélectionne les données du TCD → Insertion → Graphique → "Barres" pour le classement, "Barres empilées 100%" pour comparer la composition par catégorie entre régions.



🗄️ En SQL

Compétences réactivées : M06-M09

  1. Dans ta feuille Excel nettoyée, exporte les données au format CSV (Fichier → Enregistrer sous → CSV).
  2. Importe ce CSV dans sqliteonline.com (Import dans le menu du haut).
  3. Écris la requête qui reproduit ton TCD : total par région, filtré sur 2015 et les 7 catégories d'infrastructures, trié par ordre décroissant.
  4. Écris une deuxième requête qui donne, pour une région de ton choix, le détail par catégorie (pas juste le total).
👉 Correction
sqlSELECT region, SUM(effectif) AS total_infra_2015
FROM sante
WHERE annee = 2015
  AND categorie IN (
    'Cabinets dentaires',
    'Etablissements Sanitaires de Premier Contact (ESPC)',
    'CHR',
    'Laboratoires d''analyse',
    'Blocs opératoires',
    'Services de radiologie',
    'Hôpitaux Généraux (HG)'
  )
GROUP BY region
ORDER BY total_infra_2015 DESC;

Compare ce résultat à ton TCD Excel — même classement, mêmes totaux.

Détail par catégorie pour une région :

sqlSELECT categorie, SUM(effectif) AS total
FROM sante
WHERE annee = 2015 AND region = 'NOM_DE_LA_REGION'
GROUP BY categorie
ORDER BY total DESC;


🐍 En Python

Compétences réactivées : M10-M12

Recharge directement le fichier xlsx brut (pas besoin de repartir du CSV de la partie SQL), reproduis la même analyse, puis construis un graphique et une répartition par catégorie.

👉 Correction
pythonimport pandas as pd
import matplotlib.pyplot as plt

df = pd.read_excel("Statistiques sur l'hôpital ivoirienne 2009 à 2015.xlsx", sheet_name="Feuil1")
df.columns = ["annee", "region", "district", "categorie", "sous_categorie", "effectif"]
df["categorie"] = df["categorie"].str.strip()
df["region"] = df["region"].str.strip()

INFRA_CATS = ["Cabinets dentaires",
              "Etablissements Sanitaires de Premier Contact (ESPC)",
              "CHR", "Laboratoires d'analyse", "Blocs opératoires",
              "Services de radiologie", "Hôpitaux Généraux (HG)"]

infra_2015 = df[(df["annee"] == 2015) & (df["categorie"].isin(INFRA_CATS))]

resultat = infra_2015.groupby("region")["effectif"].sum().sort_values(ascending=False)
resultat.head(5)

# Graphique en barres du classement
resultat.head(10).plot(kind="barh")
plt.gca().invert_yaxis()
plt.xlabel("Total infrastructures 2015")
plt.title("Classement régional — infrastructures de santé 2015")
plt.show()

# Répartition par catégorie pour les 5 régions en tête et les 5 en queue
top_bottom = list(resultat.head(5).index) + list(resultat.tail(5).index)
detail = (
    infra_2015[infra_2015["region"].isin(top_bottom)]
    .pivot_table(index="region", columns="categorie", values="effectif", aggfunc="sum")
    .loc[top_bottom]
)
detail.plot(kind="bar", stacked=True)
plt.ylabel("Effectif")
plt.title("Répartition par catégorie — top 5 vs bottom 5")
plt.show()

Mêmes chiffres qu'en Excel et en SQL — si ce n'est pas le cas, vérifie le .str.strip() sur categorie.



📈 En R

Compétences réactivées : M10-M12 — en miroir de la partie Python

👉 Correction
rlibrary(readxl)
library(dplyr)
library(stringr)
library(ggplot2)

df <- read_excel("Statistiques sur l'hôpital ivoirienne 2009 à 2015.xlsx", sheet = "Feuil1")
colnames(df) <- c("annee", "region", "district", "categorie", "sous_categorie", "effectif")
df$categorie <- str_trim(df$categorie)
df$region <- str_trim(df$region)

infra_cats <- c("Cabinets dentaires",
                "Etablissements Sanitaires de Premier Contact (ESPC)",
                "CHR", "Laboratoires d'analyse", "Blocs opératoires",
                "Services de radiologie", "Hôpitaux Généraux (HG)")

infra_2015 <- df %>% filter(annee == 2015, categorie %in% infra_cats)

resultat <- infra_2015 %>%
  group_by(region) %>%
  summarise(total = sum(effectif, na.rm = TRUE)) %>%
  arrange(desc(total))

head(resultat, 5)

# Graphique en barres du classement
ggplot(head(resultat, 10), aes(x = reorder(region, total), y = total)) +
  geom_col() + coord_flip() +
  labs(title = "Classement régional — infrastructures de santé 2015", x = "", y = "Total 2015")

# Répartition par catégorie pour les 5 régions en tête et les 5 en queue
top_bottom <- c(head(resultat$region, 5), tail(resultat$region, 5))
detail <- infra_2015 %>% filter(region %in% top_bottom)

ggplot(detail, aes(x = region, y = effectif, fill = categorie)) +
  geom_col() +
  labs(title = "Répartition par catégorie — top 5 vs bottom 5", y = "Effectif") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Livrable : les 4 résultats (Excel, SQL, Python, R), identiques entre eux, les graphiques (classement + répartition par catégorie), et 3-5 phrases concrètes sur ce que tu observes — pas seulement "telle région est en tête", mais quelle catégorie d'infrastructure lui manque ou l'avantage précisément (pas de bloc opératoire ? beaucoup d'ESPC mais aucun CHR ?) et ce que ça signifie pour l'accès aux soins dans cette région.