Statistiques COVID-19 : Ne croyez que ce que vous pouvez vérifier!

On va apprendre dans ce (long) post à faire des statistiques « presque aussi bien que les pros » et au moins on saura comment elles sont faites et quelles sont leurs « faiblesses » et leurs limites (trouvez un journal qui fait une demi page de bémols sur les beaux graphiques qu’ils font et qui explique comment ils ont fait en détail pour voir… )

Introduction

La pandémie de COVID a vu naître une nouvelle guerre de l’information… entre ceux qui prétendent que le COVID n’est qu’une vaste arnaque et ceux qui prétendent que les hôpitaux sont noyés sous les non-vaccinés on est… bien!

Du point de vue des rouages qui garantissent le bon fonctionnement d’une démocratie c’est en réalité gravissime. Une démocratie repose sur la bonne information des citoyens pour qu’ils soient capables de voter en toute connaissance de cause.

C’est théoriquement le rôle du journaliste et c’est pour ça que la presse est supposée être un des piliers d’une démocratie. A partir du moment ou les informations qui circulent sont biaisées, altérées, orientées voire objectivement et honteusement fausses on se retrouve dans une situation terrible ou le citoyen doit décider de son vote sur la base d’informations à propos desquelles il ne peut être certain de rien.

Il en va au passage de même du consentement médical éclairé à l’acceptation d’une mesure « sanitaire »… que ça soit la prise d’une substance active, un vaccin, une opération, la pose d’un équipement… l’important est que le consentement soit éclairé, c’est à dire en pleine connaissance de cause de tous les tenants et aboutissants : les bénéfices mais aussi les effets indésirables, les risques et même (surtout) les incertitudes.

Et de ce point de vue là le compte n’y est clairement pas… on a toujours quelques voix dissidentes dans ces cas là mais elles sont ténues et bien entendu taxées de tous les vices et mauvaises intentions du mondes. L’étiquette à la mode étant complotiste! avec idéalement une nuance d’horreur ou de condescendance dans la voix pour faire meilleur effet.

Nota : Si vous voyez des soucoupes volantes partout ou si vous imaginez que les vaccins ARNm vont vous connecter à internet et vous faire entrer directement dans la matrice ce post va beaucoup vous décevoir je le crains. Si vous pensez que plus de 80% des malades du COVID en soins critiques sont non-vaccinés et que les hôpitaux sont saturés de malades COVID intubés vous allez aussi être déçus. Dans un cas comme dans l’autre vous gagnerez du temps en vous épargnant la lecture. Si en revanche vous êtes curieux de savoir comment on construit proprement des requêtes sur des jeux de données pour en tirer des informations exploitables et fiables et si vous voulez être capables de le faire par vous mêmes alors vous êtes au bon endroit et vous pouvez vous accrocher à vos baskets 🙂

D’où viennent les données

Ça fait partie des difficultés de départ : avant de pouvoir mettre la main dessus il faut que les données soient 1) récoltées 2) entassées ensemble quelque part 3) Mises à disposition du public.

Pour le 1) c’est pas trop difficile : beaucoup d’organismes, dont les hôpitaux, récoltent des données pour leur propres besoins de gestion… les données sont donc créées et stockées « quelque part ».

Pour le 2) l’état se dote d’organismes dédiés à ça parce que gérer un pays ça nécessite des données. On en verra un dans ce post, j’en mentionnerai d’autres.

Pour le 3) le législateur y a pourvu en théorie avec diverses dispositions favorisant l’Open Data : De nombreux organismes publics doivent publier leurs données et mettent des plates-formes à cet effet en ligne. Tous ne jouent pas le jeu à fond et tous ne publient pas les données dans des formats très faciles à « digérer » mais c’est mieux que rien et ça permet déjà de faire pas mal de choses.

En ce qui concerne les données de santé elles sont en particulier centralisées par la DREES (Direction de la Recherche, des Études, de l’Évaluation et des Statistiques, organisme indépendant mais « rattaché » au Ministère de la Santé). Leur site est là : http://drees.solidarites-sante.gouv.fr

A une époque j’avais eu l’honneur de piloter un projet de refonte de leur site ainsi que celui du Ministère de la Santé… ça a tenu quelques années et je viens de voir que le site de la DREES est passé sous Drupal 8 (Bonjour à l’équipe DirCom si vous êtes toujours en place et si vous passez par cette page ^^) .

Leur plate-forme de données est là : https://data.drees.solidarites-sante.gouv.fr et elle est plutôt riche et plutôt bien faite (bravo à l’équipe qui a conçu et mis ça en place).

Il y a d’autres sources de données : la DARES attachée au ministère du Travail ( https://dares.travail-emploi.gouv.fr ), l’INSEE (incontournable, https://www.insee.fr) ainsi que DATA GOUV (https://www.data.gouv.fr).

Le principe est (presque) toujours le même : les données sont mises à disposition sous forme de fichiers « bruts ». J’entends par « brut » des tableaux de chiffres dans des formats ultra-basiques comme le CSV (Et c’est très bien comme ça). Le CSV consiste à séparer les « colonnes » des tableaux par des points-virgules.

Ça ressemble à ça :

Exemple de données dans un fichier CSV

C’est moche, certes, mais ça a l’avantage d’être « digérable » par des tas de programmes… au plus simple on peut les convertir en tableur (genre Excel™ pour les plus microsoftiens de mes lecteurs… vous surement doutez bien que je préfère LibreOffice) mais on peut faire bien plus fin comme on va voir dans ce billet (même si au final ça peut et ça va retourner dans un tableur LibreOffice pour une présentation finale plus sympa et plus « parlante »).

Comment on les récupère ?

Ça n’est pas la partie la plus compliquée… on va sur le site qui nous intéresse… ici ça sera le site Open Data de la DREES : https://data.drees.solidarites-sante.gouv.fr

Ça ressemble à ça (et on va cliquer tout de suite sur le bouton entouré en rouge) :

Une fois cliqué sur le bouton on arrive sur un catalogue de données « disponibles »… ça ressemble à ça :

On va aller chercher «  » qui se présente dans la liste comme ci-après.

Ce fichier est un rapprochement de données fait par la DREES à partir de 3 sources :

  • SI-VIC (Les stats d’hospitalisations),
  • SI-DEP (Les stats de dépistage COVID… autrement dit : les tests) et,
  • VAC-SI (Les stats de vaccination).

C’est ce qu’on a, en tout cas aujourd’hui de plus « brut » comme données sur le sujet je crois.

On le verra en fin de billet ça n’est pas parce que des données sont « brutes » qu’elles sont exemptes de points de discussion ou de critique. Et il faut discuter des chiffres contrairement à ce que certains prétendent parce que sans ce regard critique on peut arriver à des interprétations erronées.

La liste d’icônes sur le côté est ce qui nous intéresse.

L’icône « Tableau » permet d’afficher les données sous une forme à peine plus sexy (comme un tableur mais en ligne) et n’a en réalité que très peu d’intérêt.

L’icône Analyse est très important et permet de « comprendre » la nature des données et leur unité. 1000 ne signifie pas la même chose si c’est un pourcentage, une valeur absolue ou un ratio pour 100 000 personnes… Si ces informations d’interprétation ne sont pas fournies ou qu’à moitié ou laissent un doute comme « Taux de contaminés » devenez TRÈS prudents et creusez ce sujet là en premier avant d’envisager de « jouer » avec des données qui ne veulent rien dire.

L’icone « Export » est celui qui nous intéressera ensuite : il permet de télécharger les données sous divers formats plus ou moins faciles à « digérer ».

Le dernier icône « API » (API ça veut dire Application Programming Interface) est fait pour automatiser complètement la récupération et le traitement par des programmes 100% autonomes. C’est quand même le niveau au dessus… peut être je ferai un post là dessus. Laissez moi déjà finir celui là 🙂

Voyons donc cet icône « Export »… Quand on clique dessus ça donne ça :

En cliquant sur « Jeu de données » entier en face de CSV on récupère un (plus ou moins) gros fichier. Celui qui nous intéresse.

Nota : Les formats JSON et Excel™ sont aussi disponibles mais moins intéressant pour ce qui suit, JSON est un peu moins simple à digérer que CSV et Excel est « pré-digéré » et ne permet que des traitements basiques même en utilisant les affreux « tableaux croisés dynamiques »… donc va pour CSV : c’est simple, c’est propre, ça « fait le boulot ».

Si vous voulez suivre pas à pas vous pouvez aller sur le site Open Data de la DREES dès à présent et mettre de côté le fichier que vaus aurez téléchargé.

Je vous conseille de lui donner un nom plus court et sans tirets dedans dès le téléchargement (exemple : covid_19_resultats_nationaux .csv au lieu de covid-19-resultats-issus-des-appariements-entre-si-vic-si-dep-et-vac-si.csv). La raison est que ça vous simplifiera tout à l’heure la vie au moment de l’import en base de données (si le nom de fichier est trop long et avec des tirets ça posera des soucis de nom de table).

Ensuite il va falloir commencer à jouer.

Comment on joue avec ?

Et avant tout dans quoi on les met ces données pour pouvoir les exploiter. Je ne vais pas faire de vous des experts de l’analyse de données et de la visualisation de données en un post, et encore moins des experts du « Big Data »… je n’ai pas cette ambition.

Mais comprendre les grands principes et être capables de les utiliser sur des cas simples j’espère que oui.

Je vais donc vous entraîner dans le monde de la requête, du tri et de l’agrégation de données… et pour ça il va vous falloir une base de données. Pas de panique je ne vais pas non plus vous apprendre le métier de « DBA » (DataBase Administator). On va faire dans le simple à installer, simple à utiliser, gratuit et open source : MariaDB. Et en plus je vais vous guider pas à pas.

Télécharger et installer MariaDB

Si vous êtes sous Linux : MariaDB est au catalogue d’installation… il vous suffira d’ouvrir votre outil graphique de gestion de paquets, rechercher MariaDB et cliquer sur install, pour MacOS c’est pareil avec Homebrew (pompeurs bouh!).

C’est tellement bien quand c’est simple et que ça marche sans efforts. Bon c’est pas le cas sous Windows™ donc il va falloir la jouer « à la windows » : on va commencer par aller sur la page de téléchargement avec un navigateur internet : https://mariadb.org/download

Cliquez sur le gros bouton bleu « Download » pour récupérer le fichier « MSI »

Un fichier du genre mariadb-10.6.5-winx64.msi va être récupéré dans votre répertoire Téléchargement. Exécutez ce fichier pour procéder à l’installation.

Cliquez sur « Next »

Cliquez sur « I accept… » et puis sur « Next »

Cliquez sur « Next »

Choisissez un mot de passe pour le super administrateur « root », cochez la case « Use UTF8… » et cliquez sur «  »Next »
Ne touchez à rien et cliquez sur « Next »

Cliquez sur « Install »

Cliquez sur « Oui »

Laissez faire…

Cliquez sur « Finish »

Et voilà… Dans le menu « Démarrer » à la lettre « M » il y a maintenant une entrée Maria DB :

C’est HeidiSQL qui sera votre ami pour la suite. Ça se lance depuis le menu démarrer et ça ressemble à ça :

Vous n’êtes peut être pas familiers avec ça… pour votre compréhension disons (en caricaturant beaucoup) qu’une base de données est à Excel™ ce qu’une moto de course est à une trottinette. Excel™ pourra traiter quelques dizaines de milliers de lignes, une base de données cosatud peut en traiter deux cent millions en se marrant.

La première chose à faire là dedans est de créer une nouvelle base vide pour mettre nos données dedans. Ça se fait en cliquant avec le bouton droit de la souris au beau milieu du fond blanc dans la zone-colonne de gauche. Puis choisir Créer une(e) nouveau(el/elle) -> Base de données.

Visuellement ça donne ça :

Ça va ouvrir une boite de dialogue (voir ci après) qui permet de donne le nom de la base de données en question. Dans l’image vous verrez que j’ai choisi de l’appeler « covid19 » histoire de n’être pas du tout original.

Vous verrez aussi que dans la partie basse de la fenêtre (Code CREATE) ça « explique » ce que ça va envoyer comme instruction technique au moteur de la base de données pour effectuer la tâche de création de la base:

CREATE DATABASE `covid19` /*!40100 COLLATE ‘utf8mb3_general_ci’ */

Pour effectuer la création il suffit de cliquer sur « OK »

On vient de créer une « coquille vide » (Penser : « je viens de créer un nouveau classeur ») dans laquelle on va « importer » nos donnés à partir du fichier CSV (Penser : je vais créer une nouvelle feuille/onglet dans mon classeur avec des données sous forme de tableau lignes/colonnes). Pour ça Heidi SQL est sympa, il permet de tout faire à votre place. Pour ça : cliquer dans le menu Outils -> Importer un fichier CSV. Ça ouvre une nouvelle boite de dialogue un peu grosse qui ressemble à ça :

Il faut lui donner le fichier CSV qu’on a récupéré de la DREES : On va pour ça cliquer sur le petit symbole jaune au bout de la zone de saisie « Nom de fichier » et sélectionner le fichier dans la zone de téléchargement comme ci-après.

Puis il faudra cliquer sur « Ouvrir »…

On voit que le nom du fichier et son emplacement ont été renseignés dans la zone « Nom de fichier »

Ensuite en bas à droite dans « Destination » il faut s’assurer que la base de données est bien la nôtre (covid19).

Puis dans le champ Table mettre la seule possibilité offerte :

Le résultat est spectaculaire…

Comme on peut voir dans L’illustration qui suit le Heidi SQL a été assez sympa pour analyser la « structure » sur fichier CSV et en déduire plein de choses :

  • Le nom de la table à créer (Penser : le nom de l’onglet/la feuille)
  • les champs (Penser : les colonnes et leurs noms) et leur nature (date, texte, nombre…)

Il suffit dès lors de cliquer sur « OK, créer table »

Nota : Si vous n’avez pas pris la précaution de changer le nom du fichier CSV tout à l’heure c’est ici que ça vous claquera un message d’erreur disant que le nom de table est invalide.

Il vous faudra dans ce cas éditer « délicatement » (sans rien toucher d’autre) le code CREATE TABLE proposé pour remplacer covid-19-resultats-issus-des-appariements-entre-si-vic-si-dep-et-vac-si par covid_19_resultats_nationaux.

Puis vous pourrez cliquer sur le bouton « importer » (il pourra y avoir quelques lignes en erreur ça peut arriver).

Nota : comme vous venez de créer une base et une table, elles n’apparaîtront pas forcément de suite… pressez la touche de fonction F5 pour rafraîchir l’affichage. Vous pourrez alors cliquer sur covid19 dans la zone-colonne de gauche et ensuite sur le nom de la table fraîchement créé. Vous arriverez à ceci :

Si vous cliquez sur l’onglet « Données » vous obtiendrez l’affichage des données brutes importées depuis le fichier CSV :

L’onglet « Requête » (avec sa petit flèche bleu va permettre beaucoup plus de choses intéressantes) :

En fonction ce ce qu’on va donner comme requête à effectuer on pourra grouper les données, les filtrer, les trier, faire des sommes, des moyennes… c’est tout l’intérêt d’une base de données ! Essayons d’abord de faire simple pour que vous compreniez le principe.

Premier exemple : affichage uniquement des données du 2 janvier 2022… la requête pour ça est :

SELECT * FROM covid_19_resultats_nationaux WHERE DATE ="2022-01-02"

Et ça donne ça comme résultat :

Si maintenant sur cette même journée je veux simplifier l’affichage du statut vaccinal (Vaccinés / Non-vaccinés) je peux utiliser des formules conditionnelles. Exemple :

SELECT DATE, IF(vac_statut = "Non-vaccinés", "Non-vaccinés", "Vaccinés") AS Statut, nb_PCR_sympt, nb_PCR+, nb_PCR+_sympt, nb_PCR FROM covid_19_resultats_nationaux WHERE DATE ="2022-01-02"

Je pousse un peu plus loin et je « groupe » les lignes par leur statut en faisant la somme des valeurs :

SELECT DATE, IF(vac_statut = "Non-vaccinés", "Non-vaccinés", "Vaccinés") AS Statut, SUM(nb_PCR_sympt), SUM(nb_PCR+), SUM(nb_PCR+_sympt), SUM(nb_PCR) FROM covid_19_resultats_nationaux WHERE DATE ="2022-01-02" GROUP BY Statut;

On peut également arrondir les valeurs pour éviter les chiffres après la virgule (surtout pour compter des humains) :

SELECT DATE, IF(vac_statut = "Non-vaccinés", "Non-vaccinés", "Vaccinés") AS Statut, ROUND(SUM(nb_PCR_sympt)), ROUND(SUM(nb_PCR+)), ROUND(SUM(nb_PCR+_sympt)), ROUND(SUM(nb_PCR)) FROM covid_19_resultats_nationaux WHERE DATE ="2022-01-02" GROUP BY Statut;

On voit quand même que l’on a les valeurs sur plusieurs colonnes pour une même date… il faut compliquer un tout petit peu la requête pour faire un groupement « fusionné ».

L’idée est ici de « balayer » trois fois la table : 1 fois pour la liste des dates, une 2eme fois pour aggéger les données « VAX » pour chaque date et une 3eme fois pour aggéger les données « NO-VAX » pour chaque date. Pour faire ça on utilise une jointure :

SELECT (tout ce qu'on veut afficher comme colonnes)
FROM matable nom1
LEFT JOIN matable nom2
ON (mettre ici les règles de correspondance nom1<->nom2) AND (critère pour récupérer les infos non-vax)
LEFT JOIN matable nom3
ON (mettre ici les règles de correspondance nom1<->nom3)  AND (critère pour récupérer les infos non-vax)
GROUP BY nom1.DATE;

Les règles de correspondance permettent d’éviter de compter plusieurs fois les mêmes lignes. On corrèle sur les champs qui permettent de garantir cette unicité des lignes : le champ de date évidemment et puis on a le champ d’effectif en fin de ligne qui peut être utilisé.

Le GROUP BY de la fin permet d’activer les fonctions d’aggrégation (nécessaires pour faire des sommes de valeurs sur plusieurs lignes) . A partir de là on peut utiliser des fonctions SUM().

Au final la requête pour récupérer nos donnés aggrégées, arrondies, groupées et colonées c’est ça :

SELECT m1.`DATE`, 
ROUND(SUM(m2.`nb_PCR`)) `NV_nb_PCR`, ROUND(SUM(m2.`nb_PCR_sympt`)) `NV_nb_PCR_sympt`, ROUND(SUM(m2.`nb_PCR+`)) `NV_nb_PCR+`, ROUND(SUM(m2.`nb_PCR+_sympt`)) `NV_nb_PCR+_sympt`, ROUND(SUM(m2.`HC`)) `NV_HC`,ROUND(SUM(m2.`HC_PCR+`)) `NV_HC_PCR+`, ROUND(SUM(m2.`SC`)) `NV_SC`, ROUND(SUM(m2.`SC_PCR+`)) `NV_SC_PCR+`, ROUND(SUM(m2.`DC`)) `NV_DC`, ROUND(SUM(m2.`DC_PCR+`)) `NV_DC_PCR+`,
ROUND(SUM(m3.`nb_PCR`)) `VAX_nb_PCR`, ROUND(SUM(m3.`nb_PCR_sympt`)) `VAX_nb_PCR_sympt`, ROUND(SUM(m3.`nb_PCR+`)) `VAX_nb_PCR+`, ROUND(SUM(m3.`nb_PCR+_sympt`)) `VAX_nb_PCR+_sympt`, ROUND(SUM(m3.`HC`)) `VAX_HC`,ROUND(SUM(m3.`HC_PCR+`)) `VAX_HC_PCR+`, ROUND(SUM(m3.`SC`)) `VAX_SC`, ROUND(SUM(m3.`SC_PCR+`)) `VAX_SC_PCR+`, ROUND(SUM(m3.`DC`)) `VAX_DC`, ROUND(SUM(m3.`DC_PCR+`)) `VAX_DC_PCR+`
FROM covid_19_resultats_nationaux m1
LEFT JOIN covid_19_resultats_nationaux m2
ON m1.`DATE` = m2.`DATE`
AND m1.effectif = m2.effectif
AND m2.vac_statut = "Non-vaccinés"
LEFT JOIN covid_19_resultats_nationaux m3
ON m1.`DATE` = m3.`DATE`
AND m1.effectif = m3.effectif
AND m3.vac_statut != "Non-vaccinés"
GROUP BY m1.DATE;

Nota: Tout ce qui est en m2.quelquechose remontera les données « non-vax » et tout ce qui est en m3.quelquechose remontera les données « vax ».

Le résultat de l’execution dans la fenêtre de HeidiSQL ressemble à ça :

Ce résultat une fois produit on peut le copier (sélectionner toutes les lignes, cliquer sur leslignes sélectionnées avec le bouton droit de la souris et survoler « copier en » puis cliquer sur « texte délimité ».) et le coller dans un tableur (type Excel ou LibreOffice Calc) pour les mettre en forme, y rajouter des calculs de % et faire des beaux graphiques qui aident à comprendre…

Si vous avez suivi l’ensemble des étapes votre tableur devrait contenir un jeu de données conforme à celui-ci (j’ai pris les données de juin 2021 au 2 janvier 2022 en prenant ce que me proposait le site de la DREES aujourd’hui) :

Je vous le fournis au format LibreOffice en défenseur convaincu des valeurs Open Source. Si vous ne l’avez pas vous pouvez le télécharger gratuitement ici : https://www.libreoffice.org/download/download/

Ue fois que vous avez la « base » il suffit d’ajouter des colonnes… pour me simplifier les mises à jour j’utilise souvent l’astuce suivante : les données « brutes » restent dans un onglet telles quelles (je peux ainsi les écraser avec des données plsu récentes sans souci) et je fais mes ajouts dans un autre onglet qui « récupère » les données du premier onglet avec des formules du genre : =$Feuille1.G189

Voici un exemple de ce qu’on peut obtenir comme mise en forme pour ces données brutes:

Ça donnes des courbes de ce genre :

Je vous invite à le télécharger, à le manipuler, à vérifier si je n’ai pas fait d’erreur. C’est tout l’intérêt d’une démarche ouverte : on peut vérifier la démarche et le raisonnement d’un bout à l’autre. C’est pour ça que j’aimerais que ces vaccins ARNm soient publiés en open source : pour que d’autres chercheurs, virologues, immunologues, épidémiologues puissent analyser les détails et vérifier tout ce qu’ils veulent vérifier : la composition, les adjuvants, les processus de fabrication…

Comment on interprète ça maintenant ?

Hé bien figurez vous que c’est tout sauf une question simple. Vous verrez souvent à la télévision ou sur twitter ges gens dire « regardez ça monte (ou ça descend) », « regardez, ça monte en même temps que… », « regardez ça descend alors que xxx monte… » et ils ajoutent souvent « on voit bien que… » ou « c’est donc évident que… »

Il faut être très prudents avec ça… ces « relations » que l’on « voit bien » sur des courbes sont des relations de CORRELATION. Ça veut dire que ça se passe « en même temps ». Ça ne veut pas forcément dire que c’est directement lié.

Si je pose sur un graphique le nombre de soigants au bout du rouleau (qui augmente) avec le nombre de pets d’ours au groendland (qui diminue, l’espèce souffrant du réchauffement climatique) et que je vous raconte que « l’on voit bien que c’est de la faute des ours du groendland si les soignants sont épuisés » c’est que j’ai raté un point fondamental : la CORRELATION c’est très différent de la CAUSALITÉ!

La corrélation c’est quand c’est « en même temps » (peut être par hasard) et la sausalité c’est quand un des deux entraine l’autre.

Cette précaution étant posée (et on verra que c’est TRÈS important) ono va essayer de tirer quelque chose de ces données puisqu’on les a produites….

Je vais mettre la suite dans un autre post… celui-ci est déjà assez long comme ça.

PS : Bravo à ceux qui se seront accrochés jusqu’au bout…