Retour à la leçon·Leçon 5 sur 8·Sortir les données
Interroger le système au lieu d'exporter à la main
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.
Ce que couvre cette leçon
- L'export mensuel est le problème
- Deux points d'accès, deux questions
- Adresser le cube
- La forme de la réponse
- Les quatre choses à régler d'abord
- Tirez aussi les métadonnées
- La suite
Notes du présentateur
Deux points d'accès qui répondent à des questions différentes, la syntaxe de dimensions qui adresse un cube, et les quatre choses à régler avant tout — authentification, pagination, limites de débit, et le fait que les tables analytiques sont périmées tant que personne ne les reconstruit.L'export mensuel est le problème
- Quelqu'un ouvre l'interface, choisit les unités d'organisation, les périodes, les éléments de données, clique sur exporter, et envoie un tableur par courriel.
Notes du présentateur
Quelqu'un ouvre l'interface, choisit les unités d'organisation, les périodes, les éléments de données, clique sur exporter, et envoie un tableur par courriel. Le mois suivant, quelqu'un recommence, légèrement différemment, et personne ne sait dire comment. C'est ce processus que cette leçon remplace. Non parce que l'interface est mauvaise — c'est ainsi que la plupart des gens devraient employer DHIS2 — mais parce qu'une analyse qui commence par un fichier bâti à la main n'est pas reproductible, et la reproduire était tout l'objet du module 2.Deux points d'accès, deux questions
Point d'accès Renvoie À employer pour /api/dataValueSetsLes valeurs brutes stockées, telles que saisies Reproduire le registre ; tout ce qui exige de voir ce qui a été tapé /api/analyticsDes valeurs agrégées et calculées Indicateurs, totaux remontés dans la hiérarchie, tout ce que le système calcule Notes du présentateur
La chose la plus utile à savoir sur l'API est qu'il existe deux façons de sortir des données et qu'elles répondent à des questions différentes.Deux points d'accès, deux questions
dataValueSetsdonne la vérité telle que stockée — une ligne par élément de données, unité d'organisation, période et…analyticsdonne la réponse que le système afficherait sur un tableau de bord — agrégée dans la hiérarchie,…- Tirez les deux quand ils sont censés concorder — Là où ils divergent, l'écart est une règle d'agrégation dont vous…
Notes du présentateur
La différence compte plus qu'il n'y paraît.dataValueSetsdonne la vérité telle que stockée — une ligne par élément de données, unité d'organisation, période et combinaison d'options de catégories. Aucune agrégation, aucune arithmétique d'indicateur, aucun remplissage. C'est ce qu'il vous faut quand l'analyse doit être défendable jusqu'à la saisie.analyticsdonne la réponse que le système afficherait sur un tableau de bord — agrégée dans la hiérarchie, indicateurs évalués, opérateurs d'agrégation appliqués. C'est ce qu'il vous faut quand il vous faut le même chiffre que celui que regarde le ministère. Tirez les deux quand ils sont censés concorder. Là où ils divergent, l'écart est une règle d'agrégation dont vous n'avez pas tenu compte, et la trouver vaut une après-midi.Adresser le cube — Exemple
GET /api/analytics.json ?dimension=dx:PENTA3_UID;BCG_UID &dimension=ou:LEVEL-4;DISTRICT_UID &dimension=pe:202401;202402;202403 &displayProperty=NAMENotes du présentateur
Les requêtesanalyticssont dimensionnelles. Vous demandez une tranche de cube, et chaque dimension porte un nom.Adresser le cube
dx— dimension de données : éléments de données, indicateurs, opérandes.ou— unités d'organisation.LEVEL-4désigne toutes les unités du niveau 4 ; y adjoindre l'UID d'un district…pe— périodes, explicites (202401) ou relatives (LAST_12_MONTHS).- Préférez les périodes explicites aux relatives dans un script —
LAST_12_MONTHSrenvoie une fenêtre différente chaque…
Notes du présentateur
Préférez les périodes explicites aux relatives dans un script.LAST_12_MONTHSrenvoie une fenêtre différente chaque mois, ce qui est commode pour un tableau de bord et fatal pour la reproductibilité. Calculez la fenêtre dans votre code, puis demandez-la nommément, pour que la requête elle-même consigne ce qui a été demandé.Adresser le cube — En Python
import requests BASE = "https://play.dhis2.org/40/api" def analytics(dx, ou, pe, session): response = session.get( f"{BASE}/analytics.json", params={ "dimension": [f"dx:{';'.join(dx)}", f"ou:{ou}", f"pe:{';'.join(pe)}"], "displayProperty": "NAME", "skipMeta": "false", }, timeout=120, ) response.raise_for_status() return response.json()Adresser le cube — En R
library(httr2) analytics <- function(dx, ou, pe) { request("https://play.dhis2.org/40/api/analytics.json") |> req_url_query( dimension = paste0("dx:", paste(dx, collapse = ";")), dimension = paste0("ou:", ou), dimension = paste0("pe:", paste(pe, collapse = ";")), displayProperty = "NAME", .multi = "explode" ) |> req_perform() |> resp_body_json() }Notes du présentateur
skipMeta=falseest délibéré. Le bloc de métadonnées porte les noms derrière chaque UID de la réponse, et sans lui vous avez un tableau d'identifiants que personne ne peut lire.La forme de la réponse — En Python
def to_frame(payload): import pandas as pd columns = [h["name"] for h in payload["headers"]] frame = pd.DataFrame(payload["rows"], columns=columns) names = {uid: item["name"] for uid, item in payload["metaData"]["items"].items()} for column in ("dx", "ou", "pe"): if column in frame: frame[f"{column}_name"] = frame[column].map(names) return frameNotes du présentateur
analyticsrenvoie un bloc d'en-têtes, un tableau de lignes et un dictionnaire de métadonnées. Transformez-le en tableau immédiatement et joignez les noms.La forme de la réponse — En R
to_frame <- function(payload) { cols <- vapply(payload$headers, \(h) h$name, character(1)) rows <- do.call(rbind, lapply(payload$rows, \(r) unlist(r))) as.data.frame(rows, stringsAsFactors = FALSE) |> setNames(cols) }La forme de la réponse
- Conservez les UID en plus des noms — Les noms changent ; les UID non
Notes du présentateur
Conservez les UID en plus des noms. Les noms changent ; les UID non. Un script qui joint sur un nom casse à la première correction orthographique, et il casse en silence, en renvoyant moins de lignes.Les quatre choses à régler d'abord
- L'authentification — Employez un jeton d'accès personnel là où l'instance le permet, l'authentification de base sinon,…
Notes du présentateur
L'authentification. Employez un jeton d'accès personnel là où l'instance le permet, l'authentification de base sinon, et ne mettez jamais l'un ni l'autre dans le script. Une variable d'environnement ou un fichier d'identifiants hors du dépôt, toujours.Les quatre choses à régler d'abord — En Python
import os session = requests.Session() session.headers["Authorization"] = f"ApiToken {os.environ['DHIS2_TOKEN']}"Les quatre choses à régler d'abord — En R
req_headers(request(url), Authorization = paste("ApiToken", Sys.getenv("DHIS2_TOKEN")))Les quatre choses à régler d'abord
- La pagination — Les points d'accès de métadonnées paginent par défaut à 50
Notes du présentateur
Un dépôt d'analyse contenant un identifiant valide pour un système d'information sanitaire national est un incident grave, et cela s'est produit assez souvent pour que ce soit la première chose qu'un relecteur doive chercher. La pagination. Les points d'accès de métadonnées paginent par défaut à 50. Les points d'accès de données renverront volontiers des millions de lignes et expireront avant.Les quatre choses à régler d'abord — En Python
def paged(url, session, page_size=1000): page = 1 while True: payload = session.get(url, params={"page": page, "pageSize": page_size}, timeout=120).json() yield payload pager = payload.get("pager", {}) if page >= pager.get("pageCount", 1): return page += 1Les quatre choses à régler d'abord — En R
# Same idea: loop until page == pageCount, and never assume one request is all of it.Les quatre choses à régler d'abord
- Le débit et la taille — Demandez un district et une année à la fois, non le pays et cinq années
- Les tables analytiques sont périmées — C'est celle qui surprend
Notes du présentateur
Le débit et la taille. Demandez un district et une année à la fois, non le pays et cinq années. Une requête qui répond en huit secondes vaut mieux qu'une qui expire à quatre-vingt-dix, et la boucle fait trois lignes. Soyez un bon citoyen d'un serveur où travaillent aussi des agents de saisie. Les tables analytiques sont périmées. C'est celle qui surprend.analyticslit des tables pré-agrégées reconstruites selon un calendrier, en général nocturne. Une donnée saisie aujourd'hui n'est pas dansanalyticstant que les tables n'ont pas tourné.dataValueSetsla voit immédiatement. Les deux points d'accès peuvent donc légitimement diverger, et la bonne réaction n'est pas d'ouvrir un ticket. Vérifiez la dernière exécution.Les quatre choses à régler d'abord — En Python
info = session.get(f"{BASE}/system/info", timeout=60).json() print(info.get("lastAnalyticsTableSuccess"))Les quatre choses à régler d'abord — En R
resp <- request(paste0(base, "/system/info")) |> req_perform() |> resp_body_json() resp$lastAnalyticsTableSuccessLes quatre choses à régler d'abord
- Consignez cet horodatage avec chaque extraction — C'est la différence entre « les chiffres ont changé » et « les…
Notes du présentateur
Consignez cet horodatage avec chaque extraction. C'est la différence entre « les chiffres ont changé » et « les chiffres ont changé parce que les tables analytiques n'avaient pas tourné quand j'ai tiré ».Tirez aussi les métadonnées — Exemple
/api/dataElements.json?fields=id,name,aggregationType,categoryCombo[id,name] /api/organisationUnits.json?fields=id,name,level,parent[id]&paging=false /api/dataSets.json?fields=id,name,periodType,organisationUnits~size /api/indicators.json?fields=id,name,numerator,denominator,indicatorType[name]Notes du présentateur
Tout ce que la leçon 1 réclamait est un point d'accès. Quatre requêtes. Elles vous donnent l'opérateur d'agrégation, la hiérarchie figée, le dénominateur des rapports attendus et les définitions d'indicateurs — soit toutes les questions que les leçons précédentes disaient qu'il faudrait poser à un collègue. Enregistrez-les à côté des données, et la leçon suivante rend cela automatique.La suite
- Vous savez poser une question au système.
Notes du présentateur
Vous savez poser une question au système. La leçon suivante rend cette interrogation reproductible — un script, une fenêtre énoncée, les métadonnées tirées en même temps, et un manifeste qui consigne exactement ce qui a été demandé et quand.