


[{"content":" Un prospect, dix façons de l\u0026rsquo;écrire : le vrai problème de qualité des données # La présence de doublons est un des problèmes les plus présents des CRM. Lorsque les équipes de vente remplissent manuellement les informations, il est fréquent de rater la présence d\u0026rsquo;un prospect et de le recréer avec des informations légèrement différentes. Par exemple, la Société Générale peut facilement être aussi renseignée sous les formes Sté Générale ou SOCIETE GENERALE SA. Sans réconciliation, les équipes commerciales démarchent le même prospect deux fois, les informations terrain sont réparties sur différents comptes, et le scoring client devient inexploitable.\nCette problématique se retrouve également dans les systèmes qui tentent de relier entre elles des bases de données créées indépendamment : CRM, référentiel fournisseurs, base de facturation. Sans identifiant commun, la reconnaissance du même fournisseur dans les différentes bases devient impossible.\nTransparence Santé en est un exemple frappant : ce registre officiel, où les entreprises pharmaceutiques déclarent les montants versés à des associations et des professionnels de santé, laisse une grande liberté aux laboratoires pharmaceutiques sur la manière de renseigner leurs bénéficiaires. Le résultat final est alors une base qui est un regroupement d\u0026rsquo;un millier de bases qui ont certes les mêmes colonnes mais possèdent leurs propres conventions.\nL\u0026rsquo;utilisation des identifiants nationaux (SIREN pour les entreprises, RNA pour les associations, RPPS pour les professionnels de santé) peut alors être la solution. Peut importe le nom attribué à un bénéficiaire, l\u0026rsquo;utilisation d\u0026rsquo;un identifiant national permet de cibler sans ambiguité une entité. Malheureusement 50 % des déclarations qui concernent des personnes morales (associations comme entreprises) n\u0026rsquo;ont aucun identifiant. Ce n\u0026rsquo;est pas un problème d\u0026rsquo;accès à l\u0026rsquo;identifiant, c\u0026rsquo;est un choix de déclaration. Les comptables des laboratoires ne valideraient probablement pas un virement sans avoir un SIREN.\nLes utilisateurs de la base Transparence Santé, souvent des journalistes sans formation data, se retrouvent donc avec une base de données peu exploitable. Ce problème dépasse largement ce cas spécifique : sans solution de déduplication, toute organisation fait face aux mêmes conséquences. Pour identifier toutes les déclarations d\u0026rsquo;une même entité, il faut retrouver manuellement toutes les variations de son nom, source d\u0026rsquo;erreurs significatives et de perte de confiance dans les données. Les impacts sont alors doubles : des surcoûts opérationnels liés au temps passé à identifier manuellement les doublons, et une perte de fiabilité des données due au démarchage en double, aux informations clients dispersées sur différents comptes, et aux analyses faussées par des incohérences.\nEuros for Docs s\u0026rsquo;attaque à ce problème. L\u0026rsquo;association a mis en place tout un système de traitement de la base Transparence Santé pour regrouper les variantes d\u0026rsquo;une même entité et permettre une analyse fiable des risques de conflit d\u0026rsquo;intérêt.\nRetrouver les doublons de professionnels de santé est relativement simple. On peut retrouver ou corriger le numéro RPPS en utilisant des informations secondaires (profession, code postal) renseignées par les laboratoires.\nPour les personnes morales, seul le nom déclaré par le laboratoire est disponible, sans format ni convention imposée. L\u0026rsquo;association ACTIV, par exemple, apparaît sous trois formes dans la base :\nASSOCIATION CLINIQUE ET THÉRAPEUTIQUE INFANTILE DU VAL DE MARNE (ACTIV) ACTIV ASS CLINIQ THERAP INFANTIL ACTIV Un humain reconnaît immédiatement la même entité. Mais les chaînes de caractères sont techniquement différentes. La suite de cet article explore différentes manières de comparer ces noms pour que les variantes d\u0026rsquo;une même entité soient considérées suffisamment proches entre elles (et différentes de variantes d\u0026rsquo;autres associations) pour être considérées comme doublon.\nDes noms si proches mais si différents # Avec des dizaines de milliers de déclarations, la déduplication manuelle est irréaliste. Sans automatisation, une exposition à des coûts opérationnels élevés et à une dégradation de la qualité des données est inévitable, ce qui impacte directement les analyses et les prises de décision. Il est donc nécessaire de trouver une représentation mathématique des noms d\u0026rsquo;associations qui permet de prendre en compte les variantes les plus fréquentes (sigles, abréviations phonétiques voire des fautes de frappe) et considérer les variantes comme similaires malgré leur apparente différence.\nLes métriques de similarité # Pour automatiser la détection des doublons, plusieurs approches existent. En voici les principales, avec leurs forces et leurs limites.\nComparaison caractère par caractère # La distance de Levenshtein compte le nombre de modifications (ajout, suppression, remplacement de lettre) nécessaires pour passer d\u0026rsquo;un nom à un autre. Cette approche est particulièrement efficace pour détecter les fautes de frappe, comme Société écrit Socité.\nCependant, elle atteint rapidement ses limites avec des variantes plus complexes. Dans notre base, le nom complet de l\u0026rsquo;ACTIV est ainsi jugé plus proche de l\u0026rsquo;association sur le diabète (41 modifications) que de son propre acronyme ACTIV (58 modifications). Comme un correcteur orthographique qui compte le nombre de touches à changer, cette méthode reste trop sensible aux différences de longueur.\nNombre de modifications nom complet ACTIV ASS CLINIQ THERAP ACTIV ASSO CLINIQUE SUR LE DIABÈTE nom complet - 39 58 41 ACTIV ASS CLINIQ THERAP - 27 22 ACTIV - 25 Comparaison intelligente # La distance de Jaro-Winkler améliore la détection en tenant compte de l\u0026rsquo;ordre des lettres similaires dans la chaîne et en accordant un bonus aux noms qui commencent de la même façon.\nnom complet ACTIV ASS CLINIQ THERAP INFANTIL ACTIV ASSO CLINIQUE SUR LE DIABÈTE nom complet - 68% 53.8% 64.3% ACTIV ASS CLINIQ THERAP INFANTIL - 71.9% 61.7% ACTIV - 56.9% Levenshtein et Jaro-Winkler partagent la même limite : elles comparent les chaînes caractère par caractère, sans tenir compte de l\u0026rsquo;importance des termes. Par exemple, ASSOCIATION apparaît dans des centaines de noms différents, mais contribue autant dans la similarité que THERAPIE ou VAL DE MARNE, pourtant bien plus discriminants.\nVers des approches plus intelligentes # Pour aller plus loin, il faut donner plus de poids aux mots rares et distinctifs comme ACTIV ou CARDIOLOGIE, et moins aux mots courants comme ASSOCIATION ou française. Les méthodes suivantes utilisent cette idée, mais avec des approches différentes.\nPondération par rareté des mots # Le TF-IDF attribue un score à chaque mot en fonction de sa fréquence dans l\u0026rsquo;ensemble du corpus. Un terme présent dans 70 % des noms, comme ASSOCIATION, reçoit un poids faible, tandis qu\u0026rsquo;un terme rare comme ACTIV en reçoit un élevé.\nSur notre base Transparence Santé, cela donne par exemple :\nTerme Fréquence dans le corpus Poids ASSOCIATION 60 239 très faible FRANCAISE 8 739 faible CARDIOLOGIE 2 29 élevé ACTIV 72 très élevé Cette approche règle le problème des préfixes génériques : deux associations qui partagent seulement CLINIQUE ne sont plus jugées similaires. À l\u0026rsquo;inverse, l\u0026rsquo;acronyme simple ACTIV a une similarité de 45 % avec son nom complet.\nnom complet ACTIV ASS CLINIQ THERAP INFANTIL ACTIV ASSO CLINIQUE SUR LE DIABÈTE nom complet - 0% 0% 7.7% ACTIV ASS CLINIQ THERAP INFANTIL - 45.2% 0% ACTIV - 0% Cependant, la méthode reste limitée face aux abréviations : CLINIQ et CLINIQUE sont deux mots distincts, et comme montré dans la dernière colonne, l\u0026rsquo;association sur le diabète a une similarité de 0 % avec deux variantes de l\u0026rsquo;ACTIV car aucun mot ne correspond.\nComme un moteur de recherche qui donne plus de poids aux mots uniques de votre requête, cette méthode est plus fine, mais pas parfaite.\nAnalyse par morceaux de mots # Les shingles contournent ce problème en ne travaillant plus sur les mots mais sur les suites de caractères. Chaque nom est découpé en trigrammes, des suites de trois lettres consécutives.\nPrenons l\u0026rsquo;exemple de l\u0026rsquo;ASSOCIATION CLINIQUE ET THÉRAPEUTIQUE INFANTILE DU VAL DE MARNE et de sa variante abrégée ACTIV ASS CLINIQ THERAP INFANTIL :\nASSOCIATION CLINIQUE ET THÉRAPEUTIQUE INFANTILE DU VAL DE MARNE → trigrammes: [ass, soc, oci, iat, ati, tio, ion, cli, lin, ini, niq, iqu, que, ... , mar, arn, rne] ACTIV ASS CLINIQ THERAP INFANTIL → trigrammes: [act, cti, tiv, ass, cli, lin, ini, niq, ..., inf, nfa, fan, ant, nti, til] Communs : ass, soc, cli, lin, ini, niq, the, rap, ape, inf, nfa, fan, ant, nti, til Les trigrammes communs comme ass, soc, cli, lin, ini, niq, the, rap permettent de reconnaître que ces deux noms se rapportent à la même entité, même si les mots complets sont différents.\nAlors que le TF-IDF sur les mots entiers ne trouve aucun mot commun entre l\u0026rsquo;ASSOCIATION CLINIQUE ET THÉRAPEUTIQUE DU VAL DE MARNE et ACTIV ASS CLINIQ VAL MARNE et conclut à une similarité nulle, les shingles, eux, retrouvent les trigrammes de ACTIV dans les deux variantes, de ASS et CLINIQ dans ASSOCIATION CLINIQUE, et de VAL MARNE dans les deux versions. Cette granularité fine leur permet d\u0026rsquo;identifier une similarité entre les deux variantes, là où le TF-IDF échouait complètement.\nnom complet ACTIV ASS CLINIQ THERAP INFANTIL ACTIV ASSO CLINIQUE SUR LE DIABÈTE nom complet - 42.4% 0% 40.2% ACTIV ASS CLINIQ THERAP INFANTIL - 40.1% 33.6% ACTIV - 0% Comme un puzzle où les pièces communes permettent de reconnaître qu\u0026rsquo;ils vont ensemble, cette méthode est particulièrement efficace pour les abréviations.\nCompréhension du sens # Le TF-IDF sur shingles couvre les abréviations et fautes de frappe, mais reste aveugle à la sémantique : cœur et cardiologie produisent des trigrammes entièrement différents, et leur similarité sera nulle malgré leur proximité de sens.\nLa méthode Doc2Vec va plus loin : elle comprend le sens des mots, pas juste leur orthographe. Cœur et cardiologie sont ainsi reconnus comme similaires, même s\u0026rsquo;ils n\u0026rsquo;ont aucun trigramme en commun. Comme un traducteur qui comprend que voiture et automobile veulent dire la même chose, cette approche capte les relations sémantiques.\nEn pratique, Doc2Vec et TF-IDF+shingles sont complémentaires : l\u0026rsquo;un capte la similarité morphologique (les abréviations), l\u0026rsquo;autre la similarité sémantique (le sens).\nConclusion # Levenshtein et Jaro-Winkler fonctionnent bien pour des noms propres de personnes, où les variations sont faibles et prévisibles. Pour des noms d\u0026rsquo;associations, elles échouent : le même préfixe générique peut dominer le score et masquer des différences réelles, ou au contraire une abréviation peut rendre deux variantes du même nom méconnaissables.\nLe TF-IDF sur shingles de caractères règle la majorité de ces cas : il pondère les termes par leur rareté et traite les abréviations morphologiquement proches comme équivalentes. Doc2Vec ajoute une couche sémantique, utile quand les formes divergent trop pour partager des n-grammes.\nPour choisir la bonne approche selon votre problème, voici un guide pratique :\nVotre problème Méthode recommandée Quand éviter ? Fautes de frappe Levenshtein / Jaro-Winkler Abréviations, mots génériques Mots distinctifs TF-IDF Abréviations Abréviations Shingles Sémantique Sémantique Doc2Vec Abréviations pures Aucune de ces métriques n\u0026rsquo;est parfaite prise isolément. C\u0026rsquo;est pourquoi EuroForDocs les combine toutes dans un modèle entraîné sur des paires annotées manuellement. Le modèle produit un score de probabilité de doublon pour chaque paire de bénéficiaires, permettant une réduction significative des coûts opérationnels et une amélioration de la fiabilité des données.\nUn prochain article détaillera comment le machine learning permet de toutes les utiliser en même temps pour scorer automatiquement la similarité entre les noms.\n","date":"September 29, 2026","externalUrl":null,"permalink":"/articles/similarite_assos/","section":"Articles","summary":"Un prospect, dix façons de l’écrire : le vrai problème de qualité des données # La présence de doublons est un des problèmes les plus présents des CRM. Lorsque les équipes de vente remplissent manuellement les informations, il est fréquent de rater la présence d’un prospect et de le recréer avec des informations légèrement différentes. Par exemple, la Société Générale peut facilement être aussi renseignée sous les formes Sté Générale ou SOCIETE GENERALE SA. Sans réconciliation, les équipes commerciales démarchent le même prospect deux fois, les informations terrain sont réparties sur différents comptes, et le scoring client devient inexploitable.\n","title":"Quand du texte libre est votre seul identifiant : des métriques pour détecter les doublons","type":"articles"},{"content":"La France compte des centaines de milliers d\u0026rsquo;associations, de la petite structure locale aux organisations de plusieurs milliers de membres. Pour mener à bien leurs activités, ces associations dépendent souvent de financements publics, notamment des subventions distribuées par les collectivités locales : communes, départements, régions.\nPourtant, cet argent public est dispersé à travers des milliers de collectivités de tailles et budgets différents, ce qui complique le contrôle de la transparence. Si les collectivités ont désormais l\u0026rsquo;obligation de publier la répartition des subventions qu\u0026rsquo;elles octroient, cette décentralisation signifie qu\u0026rsquo;il n\u0026rsquo;existe aucun système centralisé pour récupérer ces données. Elles se trouvent éparpillées sur le web : sur la plateforme data.gouv.fr, sur les sites des municipalités, parfois sous forme de PDF à télécharger.\nÀ l\u0026rsquo;approche des élections municipales de 2026, l\u0026rsquo;association Anticor a souhaité créer un outil centralisé permettant aux citoyens de suivre les subventions octroyées par leurs collectivités et de les comparer avec celles d\u0026rsquo;autres territoires. Un tel outil permettrait également d\u0026rsquo;identifier les collectivités qui ne respectent pas leurs obligations de transparence.\nPour réaliser ce projet, les associations Anticor et Transparency International France se sont associées à Data For Good afin de mobiliser des bénévoles. En 3 mois, des experts data bénévoles ont créé la plateforme Éclaireur Public. Ce projet a combiné de la récupération de données, de la normalisation des sources et du développement web pour proposer une cartographie de niveaux de publication.\nSur ce projet, j\u0026rsquo;ai pris un rôle officieux de tech lead sur la partie d\u0026rsquo;identification et de normalisation des données. Cet article présente les défis techniques et les solutions développées pour travailler avec ces données ouvertes hétérogènes.\nLe projet s\u0026rsquo;organise autour de trois grandes étapes.\nIdentifier sur le web les fichiers de déclarations de subventions publiés par les différentes collectivités. Uniformiser tous ces fichiers et les lire pour permettre de créer une base de données commune. Exploiter cette base de données pour proposer aux citoyens et utilisateurs de la plateforme non pas des données brutes, mais des statistiques descriptives et des visualisations. Récupération des données # Contrairement à d\u0026rsquo;autres obligations de déclaration comme les rémunérations des médecins pars les laboratoires pharmaceutiques, les données de subventions n\u0026rsquo;ont pas de plateforme centralisée. Chaque collectivité peut alors choisir de publier à sa manière, avec son propre format. Une des premières difficultés du projet est alors d\u0026rsquo;identifier où les collectivités qui déclarent déposent leurs documents, pour créer un catalogue de données concernant les subventions.\nPlateformes d\u0026rsquo;open data\nPour cette première version du projet, l\u0026rsquo;équipe s\u0026rsquo;est concentrée sur la plateforme data.gouv.fr qui recense une très grande variété à la fois de jeux de données mais aussi de producteurs de données. Cette plateforme recense des données d\u0026rsquo;institutions telles que l\u0026rsquo;État jusqu\u0026rsquo;à des petites collectivités. Certaines collectivités se permettent d\u0026rsquo;avoir leur propre plateforme d\u0026rsquo;open data, tout en maintenant un lien entre data.gouv.fr et leurs propres données. Par exemple, la métropole Rennaise a sa propre plateforme d\u0026rsquo;open data qui contient bien un fichier de subventions aux associations, mais on retrouve les mêmes données sur data.gouv. En y regardant de plus près l\u0026rsquo;url de téléchargement du fichier CSV depuis data.gouv pointe en réalité vers la plateforme de la métropole. Ainsi, même si certaines métropoles possèdent leurs propres plateformes, data.gouv reste un point central pour rechercher et collecter des fichiers de subventions.\nLe deuxième challenge est alors d\u0026rsquo;identifier les datasets qui correspondent à des subventions aux associations parmi l\u0026rsquo;énorme diversité que propose data.gouv. Par exemple, pour rester sur l\u0026rsquo;exemple de Rennes, le fichier de subvention est déposé aux cotés d\u0026rsquo;un fichier sur les vergers partagés ou les menus des cantines de la métropole.\nIdentification des datasets de subvention\nNotre première étape de la pipeline consiste donc à identifier sur data.gouv les jeux de données qui semblent concerner des subventions publiques. data.gouv possède justement un catalogue qui recense l\u0026rsquo;ensemble de fichiers présents sur la plateforme. Pour chaque fichier, un ensemble de metadonnées sont disponibles telles que le titre, la description ou l\u0026rsquo;url de téléchargement.\nNous sélectionnons alors les fichiers qui contiennent certains mots clés (tels que subvention) dans leur titre ou leur description. Cette pré-sélection est assez grossière et va potentiellement cibler des fichiers qui ne correspondent pas aux subventions qui nous intéressent. Ce sera l\u0026rsquo;un des rôles de l\u0026rsquo;étape suivante de normalisation de filtrer ces faux positifs.\nLe catalogue data.gouv met à disposition les métadonnées de tous les datasets de la plateforme Obsolescence des liens\nDurant le projet, nous avons fait face à un problème de disponibilité des données. Sans raisons apparentes, les url fournies par le catalogue devenaient obsolètes : les producteurs des données avaient supprimé leurs données. A l\u0026rsquo;inverse, certains fichiers avaient été modifiés pour ajouter les subventions les plus récentes mais supprimer les plus anciennes. Or, un des objectifs du projet est de proposer un suivi de la qualité des déclarations des collectivités. Nous avons donc besoin de conserver les données. Nous avons alors du mettre en place un système d\u0026rsquo;historisation des fichiers pour garder trace des changements.\nNormalisation des fichiers # La décentralisation des déclarations pose problème lors de la lecture des fichiers. Chaque collectivité peut publier sa déclaration avec sa propre convention; ce qui nous donne une grande variété de situations à considérer.\nL\u0026rsquo;objectif du projet est de créer une grande base de données unifiée de toutes les subventions de toutes les collectivités. Nous avons donc besoin d\u0026rsquo;une étape de normalisation des données pour transformer la diversité des fichiers en une convention unique. Au minimum, nous cherchons à identifier et normaliser ces informations essentielles :\nle SIREN de la collectivité, le SIREN de l\u0026rsquo;association, le montant de la subvention. Identification du format # La première difficulté consiste à identifier le format du fichier lui-même (par exemple excel, csv ou parquet). data.gouv.fr permet en théorie aux collectivités de le renseigner. Mais encore une fois le manque de convention génère une grande diversité. Pour le type de fichier le plus simple, le CSV, on voit dans le champs format des choses comme CSV, csv, fichier plat, voire texte séparé par virgules. Nous cherchons alors la présence de certaines chaines de caractères pour normaliser ce champs format et faciliter le travail en aval. Finalement, nous ne pourrons continuer à traiter que les fichiers CSV, Excel, JSON et Parquet.\nLes collectivités proposent régulièrement le même fichier de subvention en plusieurs formats, généralement CSV et JSON. Notre première recherche par mots-clés dans le catalogue data.gouv sélectionne donc toutes les versions présentes d\u0026rsquo;un même jeu de données. Nous sommes donc à risque d\u0026rsquo;intégrer plusieurs fois les mêmes données et surestimer les montants versés par les collectivités. En comparant les titres et descriptions des fichiers nous sommes capables d\u0026rsquo;identifier des doublons dans des formats différents.\nMais tous les formats de fichiers ne se valent pas en termes de facilité de lecture, en particulier lorsqu\u0026rsquo;il faut les lire en grand nombre de manière automatique. Comme nous le verrons plus loin, la lecture de fichiers CSV nécessite de connaître plusieurs paramètres que l\u0026rsquo;on devra deviner. A l\u0026rsquo;inverse, un fichier de type parquet se lit très facilement. Lorsque nous avons accès à plusieurs format d\u0026rsquo;un même jeu de données, nous pouvons sélectionner le format le plus pratique pour la lecture.\nLecture des fichiers # Comme mentionné à la section précédente, tous les formats de fichiers ne présentent pas les mêmes difficultés pour la lecture. Dans cette section, je présente les formats de fichier que l\u0026rsquo;on a pu exploiter ainsi que leurs caractéristiques qui facilitent ou compliquent leur exploitation.\nFichiers Parquet\nLes fichiers Parquet sont un format normalisé et compressé qui peuvent être lus automatiquement sans traitement particulier. Ils sont en général plus légers que l\u0026rsquo;équivalent dans d\u0026rsquo;autres formats, mais sont plutôt réservés aux professionnels de la data car le résultat n\u0026rsquo;est pas directement lisible dans Excel. Ce format reste assez peu répandu au sein des collectivités.\nFichiers Excel\nLes fichiers Excel sont un peu moins standardisés. Nous pouvons facilement extraire chaque élément des données grâce au format Excel, mais nous ne sommes pas assurés que le type de données extrait soit correct. Par exemple, le numéro SIREN d\u0026rsquo;une collectivité est fondamentalement une chaîne de caractères. Mais pour l\u0026rsquo;immense majorité des entités qui possèdent un SIREN, celui-ci contient principalement des chiffres et est donc souvent interprété comme un entier. Comme nous connaissons le type des informations que nous recherchons, nous pouvons appliquer une transformation pour formatter correctement les colonnes qui mentionnent un SIREN.\nFichiers CSV\nLes fichiers CSV sont les types de fichiers les plus représentés en open data aujourd\u0026rsquo;hui, mais présentent davantage de difficultés.\nLa première étape pour lire un CSV est d\u0026rsquo;identifier l\u0026rsquo;encodage des caractères, c\u0026rsquo;est-à-dire la manière dont chaque lettre est encodée par la machine. Le standard le plus utilisé aujourd\u0026rsquo;hui s\u0026rsquo;appelle UTF-8 et prend en charge de nombreuses lettres particulières de différents langages. Cependant, les systèmes Windows et l\u0026rsquo;administration française ont tendance à utiliser un autre standard, plus occidental, ce qui entraîne une impossibilité de lire les fichiers si l\u0026rsquo;on ne renseigne pas correctement l\u0026rsquo;encodage utilisé. Dans un système de lecture automatique de CSV, nous n\u0026rsquo;avons aucun moyen de savoir a priori le standard utilisé. Nous devons donc tester les standards les plus probables et ne garder que celui qui fonctionne.\nDans un fichier CSV, les valeurs des données sont séparées par un caractère conventionnel, historiquement la virgule, d\u0026rsquo;où le nom du format \u0026ldquo;comma separated values\u0026rdquo;. Ce standard a beaucoup évolué et différents types de caractères sont utilisés par différentes collectivités pour séparer les données. On peut retrouver aussi bien des virgules que des points-virgules, des barres verticales ou même des tabulations. Un petit outil dédié nous permet d\u0026rsquo;analyser les premières lignes du fichier pour identifier ce séparateur.\nFichiers JSON\nLe format JSON est le format le plus complexe que nous ayons intégré. Ce format écrit des données en texte brut (comme le CSV) mais, au lieu d\u0026rsquo;une structure en lignes et colonnes, les informations sont organisées sous forme de clés-valeurs. Les valeurs pouvant également être une collection de clés-valeurs, on se retrouve avec une structure hiérarchique qui diffère dans chaque fichier et crée des difficultés pour identifier les données d\u0026rsquo;intérêt. Les données de subventions que nous recherchons peuvent être organisées de différentes manières : être mélangées avec des statistiques, des métadonnées ou toute autre information que le producteur de la donnée a souhaité intégrer.\nLa mairie de Boé que nous avons vu plus haut nous propose le cas le plus simple d\u0026rsquo;un json. Le fichier (dont nous ne représentons ici que les premières lignes) ne se compose que de structures représentant des déclarations. Ainsi le premier élément compris entre {} concerne une subvention de 150€ pour une association climatologique.\n[ { \u0026#34;Nom de l\u0026#39;association\u0026#34;: \u0026#34;ACMG CLIMATOLOGIQUE\u0026#34;, \u0026#34;Secteur\u0026#34;: \u0026#34;SERVICES\u0026#34;, \u0026#34;Montant Subvention\u0026#34;: 150 }, { \u0026#34;Nom de l\u0026#39;association\u0026#34;: \u0026#34;ADOT 47\u0026#34;, \u0026#34;Secteur\u0026#34;: \u0026#34;SOLIDARITÉ\u0026#34;, \u0026#34;Montant Subvention\u0026#34;: 150 }, { \u0026#34;Nom de l\u0026#39;association\u0026#34;: \u0026#34;ALLIANCE 47\u0026#34;, \u0026#34;Secteur\u0026#34;: \u0026#34;SOLIDARITÉ\u0026#34;, \u0026#34;Montant Subvention\u0026#34;: 200 }, { \u0026#34;Nom de l\u0026#39;association\u0026#34;: \u0026#34;AMICALE LAIQUE DE BOE\u0026#34;, \u0026#34;Secteur\u0026#34;: \u0026#34;CULTURE/LOISIRS\u0026#34;, \u0026#34;Montant Subvention\u0026#34;: 1300 } ] Pour lire de manière massive ce type de fichier, nous devons faire des hypothèses quant à la structure des fichiers. L\u0026rsquo;exemple précédent est la manière la plus standard de documenter des subventions. Mais cette structure peut être placée au sein d\u0026rsquo;autres structures dans le fichier. Notre stratégie est alors de trouver dans le fichier une partie qui contient une grande liste de structures. Lorsque nous trouvons ce schéma, nous considérons que la liste représente l\u0026rsquo;ensemble des lignes de notre fichier de subvention. Il est donc tout à fait possible d\u0026rsquo;extraire un élément du fichier qui ne représente pas les subventions mais d\u0026rsquo;autres informations fournies par la collectivité. C\u0026rsquo;est l\u0026rsquo;étape suivante qui nous permettra de détecter ce genre de cas et de potentiellement imposer une extraction plus spécifique pour ce fichier.\nCompréhension des colonnes # Une fois que nous avons extrait les données telles qu\u0026rsquo;elles ont été saisies par la collectivité, il nous reste à comprendre quelles données ont été publiées et avec quelle convention. En pratique, cela signifie faire correspondre les colonnes du fichier avec la nomenclature que nous avons définie arbitrairement.\nTypes de données recherchées\nNous distinguons deux niveaux d\u0026rsquo;intérêt pour les données.\nUn ensemble de données sont considérées comme essentielles. Sans elles, on ne peut pas utiliser le fichier pour l\u0026rsquo;usage le plus simple : représenter le montant versé par collectivité et par année. L\u0026rsquo;absence d\u0026rsquo;une de ces informations nous fait rejeter ces informations. Dans cette catégorie on inclue:\nidentifiant de la collectivité (nom ou SIREN de préférence), identifiant de l\u0026rsquo;association (SIREN), montant versé, la date (ou au minimum l\u0026rsquo;année) de la subvention. Les informations secondaires représentent des notions qui peuvent enrichir la connaissance sur la subvention mais ne sont pas nécessaires pour nos calculs de scores principaux. Ces informations sont par exemple la description de l\u0026rsquo;association, la répartition des montants ou différentes dates de versement.\nCompréhension des colonnes\nChaque collectivité va avoir sa propre convention pour désigner les différents concepts. Par exemple, dans l\u0026rsquo;exemple précédent de la mairie de Boé, le champ Nom de l'association identifie le bénéficiaire de la subvention par le nom commun. Une autre collectivité pourrait nommer la même information nom_association ou Nom du bénéficiaire. Nous devons donc tenter de comprendre les différentes logiques utilisées par les collectivités et trouver les mots clés qui nous permettent d\u0026rsquo;identifier les concepts que l\u0026rsquo;on recherche.\nCe mécanisme présente toutefois des limites. Quelquefois, le titre de la colonne peut correspondre à plusieurs concept. Nous devons alors faire un choix, parfois arbitraire. Parfois, l\u0026rsquo;analyse du contenu de la colonne peut aider; en identifiant par exemple si une colonne association contient un nom pour un SIREN.\nRecherche dans les métadonnées\nSi nous n\u0026rsquo;arrivons pas à trouver certaines informations dans le fichier (telles qu\u0026rsquo;une date ou le nom de la collectivité), nous allons analyser le titre et la description du fichier pour tenter de les retrouver puis de les ajouter au fichier. Toujours dans notre exemple précédent, les informations fournies sur les subventions sont minimalistes : le nom de l\u0026rsquo;association et le montant. C\u0026rsquo;est donc à travers le nom de l\u0026rsquo;organisation déclarante que nous pouvons obtenir le nom de la collectivité et par le nom du fichier que nous pouvons obtenir, au minimum, l\u0026rsquo;année de la subvention.\nNormalisation des valeurs # La dernière étape de notre traitement de fichiers consiste à normaliser les données. Même une notion aussi simple qu\u0026rsquo;un montant de subvention peut apparaître sous de multiples formes.\nMontant\nDans une situation idéale, le montant de la subvention est directement interprété comme un nombre dès la lecture du fichier source. Cependant, comme la France utilise la virgule pour séparer les décimales (contrairement aux pays anglophones qui utilisent le point), donc un nombre à virgule sera souvent interprété comme une simple chaîne de caractères. Des espaces peuvent aussi être présents pour séparer les milliers et le signe euro peut également être présent. Nous appliquons donc une série de nettoyages sur les chaînes de caractères représentant les montants pour pouvoir les interpréter comme des nombres. Nous nous assurons que les chaînes de caractères suivantes (\u0026ldquo;1,500 €\u0026rdquo;, \u0026ldquo;2 500 euros\u0026rdquo;, \u0026ldquo;3,500.00\u0026rdquo;) sont bien interprétées comme respectivement (1500, 2500, 3500).\nIdentifiant\nLa manière la plus fiable d\u0026rsquo;identifier une collectivité ou une association est l\u0026rsquo;utilisation du numéro SIREN. Ce numéro a deux variantes souvent utilisées de manière interchangeable.\nLe numéro SIREN est lié à l\u0026rsquo;entité juridique et une chaîne de caractères (presque exclusivement des chiffres) à 9 éléments. Lorsque l\u0026rsquo;identifiant ne contient pas de lettre, il est souvent interprété comme un entier. Les zéros initiaux peuvent alors disparaître.\nLe numéro SIRET est aussi régulièrement utilisé en lieu et place du SIREN. Ce numéro fait référence à chacun des lieux physiques que possède une entité. Il se compose de 15 caractères dont les 9 premiers correspondent au numéro SIREN.\nNous avons choisi arbitrairement de normaliser les identifiants vers le numéro SIREN. À travers une série de vérifications du nombre de caractères et d\u0026rsquo;ajout de zéros manquants, nous pouvons nettoyer et normaliser les colonnes d\u0026rsquo;identifiant.\nNoms des entités\nLes noms des entités (collectivités ou associations) sont parmi les données les plus hétérogènes que nous traitons. En effet, deux collectivités n\u0026rsquo;écrirons pas de la même manière le nom d\u0026rsquo;une même association. Cet article détaille cette problématique sur un autre projet. Afin de faciliter la recherche de l\u0026rsquo;ensemble des subventions d\u0026rsquo;une collectivité ou association pour nos utilisateurs, notre objectif est de fusionner ces différentes variantes en un même nom.\nL\u0026rsquo;exemple de la mairie de Boé illustre un cas particulier : la collectivité ne fournit aucun identifiant, que ce soit pour elle-même ou pour les associations bénéficiaires. Il existe sur data.gouv.fr un fichier qui permet de relier l\u0026rsquo;identifiant data.gouv de la collectivité avec son SIREN. Ce fichier avait été créé suite à une étude pour évaluer le degré d\u0026rsquo;appropriation de l\u0026rsquo;open data par les collectivités. Ce fichier peut alors nous permettre de retrouver le siren de la collectivité (et donc son nom). Notre exploration des collectivités sur data.gouv nous a même permis de mettre à jour ce fichier.\nEn revanche, il est plus difficile d\u0026rsquo;attribuer un SIREN à une association en ne se basant que sur son nom. Il faudrait mettre au point une analyse comparative entre le nom documenté et les noms officiels. En l\u0026rsquo;état, le projet n\u0026rsquo;a pas ce type de mécanisme. Si une association est nommée de deux manière différentes par deux collectivités et qu\u0026rsquo;aucun SIREN n\u0026rsquo;est fourni, les deux variantes vont rester sous forme de doublon dans la base finale.\nGestion des erreurs # Tout le processus de normalisation des fichiers que nous venons de décrire repose sur plusieurs étapes empiriques basées sur des exemples. Il est donc courant de rencontrer des fichiers qui proposent de nouveaux cas particuliers : nouveaux séparateurs pour les CSV ou nouveaux mots-clés à extraire pour identifier le sens d\u0026rsquo;une colonne.\nUn des objectifs du projet est d\u0026rsquo;arriver à traiter un maximum de fichiers malgré la diversité. Nous avons donc mis au point un système qui organise les fichiers que nous n\u0026rsquo;arrivons pas à traiter en fonction du type d\u0026rsquo;erreur. Par exemple, nous listons les fichiers pour lesquels le téléchargement a échoué séparément de ceux pour lesquels le fichier CSV semble ne pas avoir de nom de colonne.\nCette compilation d\u0026rsquo;erreurs, qui représente plus d\u0026rsquo;une centaine de fichiers, sert de guide pour orienter les futures améliorations du projet.\nTypes d\u0026rsquo;erreurs rencontrées\nLes erreurs les plus fréquentes sont les suivantes :\nDes colonnes d\u0026rsquo;identifiant avec un nom très particulier qui ne sont pas détectées par les dictionnaires de mots-clés. Ces cas nécessitent une analyse manuelle pour identifier le pattern et l\u0026rsquo;ajouter au dictionnaire.\nDes fichiers dont le format n\u0026rsquo;est pas pris en compte par notre pipeline : principalement des fichiers PDF et HTML. Ces formats nécessitent des traitements spécifiques que nous n\u0026rsquo;avons pas encore intégrés.\nDes fichiers CSV ou Excel qui n\u0026rsquo;ont pas de nom de colonnes et dont nous ne pouvons pas identifier le sens des colonnes individuelles. Sans noms de colonnes, il est difficile de faire le mapping avec notre nomenclature.\nDes fichiers qui sont des archives zippées mais dont le format déclaré n\u0026rsquo;est pas ZIP mais le format du fichier à l\u0026rsquo;intérieur de l\u0026rsquo;archive (CSV par exemple). Notre système tente alors de lire directement le fichier comme un CSV, ce qui échoue car il s\u0026rsquo;agit en réalité d\u0026rsquo;une archive.\nPipeline d\u0026rsquo;enrichissement # Les déclarations de subventions forment le cœur du projet Éclaireur Public et représentent les données les plus complexes à collecter. Cependant, data.gouv.fr contient d\u0026rsquo;autres données qui permettent d\u0026rsquo;enrichir les analyses que l\u0026rsquo;on peut effectuer sur les collectivités.\nDonnées de marchés publics\nEn plus des subventions, nous avons également accès en ligne aux données sur les attributions de marchés publics. Ces données ont l\u0026rsquo;avantage d\u0026rsquo;avoir été centralisées et uniformisées, ce qui permet de les intégrer aux analyses via le téléchargement d\u0026rsquo;un unique fichier. Ce fichier est fourni au format JSON avec une structure hiérarchique complexe. Comme toute l\u0026rsquo;information est contenue dans un seul fichier, il est possible de créer un code spécifique et rigoureux pour ce format.\nDonnées financières\nL\u0026rsquo;open data nous permet également d\u0026rsquo;obtenir les derniers comptes de résultats des différentes collectivités. À travers quatre fichiers (ville, communauté de communes, département, région), nous pouvons comparer les subventions aux autres indicateurs financiers des collectivités et créer des métriques qui permettent de regrouper les collectivités en groupes comparables.\nDonnées sur les élus\nLes porteurs du projet étant des associations de lutte contre la corruption et les conflits d\u0026rsquo;intérêt, le projet a également inclus des données sur les élus des différentes collectivités ainsi que leurs déclarations d\u0026rsquo;intérêt. Ces données permettent de croiser les informations sur les subventions avec les déclarations d\u0026rsquo;intérêt des élus.\nSystème de scoring\nÀ partir de toutes les informations que nous avons regroupées sur les collectivités, nous pouvons les évaluer sur plusieurs aspects de leur transparence.\nLe score de transparence des subventions évalue la cohérence entre les subventions effectivement déclarées dans les bases de données publiques et les subventions budgétées dans les comptes financiers officiels. Un taux proche de 100% indique une bonne correspondance entre ce qui est déclaré et ce qui est budgété. Un taux trop faible suggère une sous-déclaration, voire une non-déclaration, tandis qu\u0026rsquo;un taux trop élevé peut indiquer un problème de comptage ou de traitement de notre part. Ce score permet d\u0026rsquo;identifier les collectivités qui respectent leurs obligations de transparence et celles qui ont des écarts significatifs.\nLe score de qualité des marchés publics évalue la qualité et la complétude des données publiées. Il prend en compte plusieurs critères progressifs : la présence de données, leur complétude (montant, dates, lieux, procédures, etc.) et le respect des délais de publication.\nConclusion # Le projet Éclaireur Public illustre les défis techniques que pose le travail avec des données ouvertes hétérogènes. L\u0026rsquo;absence de normalisation dans la publication des subventions par les collectivités crée une diversité de formats, de conventions et de structures qui complique leur traitement automatique.\nLa pipeline développée permet de traiter une majorité des fichiers identifiés sur data.gouv.fr grâce à une approche itérative basée sur des règles empiriques. Les étapes de normalisation, de mapping des colonnes et de gestion des erreurs permettent d\u0026rsquo;unifier progressivement des données disparates en une base commune exploitable.\nL\u0026rsquo;enrichissement avec d\u0026rsquo;autres sources de données ouvertes (marchés publics, comptes financiers, données sur les élus) permet d\u0026rsquo;évaluer la transparence des collectivités selon plusieurs dimensions. Les scores développés offrent aux citoyens un moyen de comparer les pratiques de transparence entre collectivités et d\u0026rsquo;identifier celles qui respectent leurs obligations.\nLe projet reste en évolution continue. Les fichiers non traités servent de guide pour améliorer la pipeline et étendre progressivement la couverture des collectivités. Cette approche itérative est nécessaire face à la diversité des pratiques de publication, qui évolue au fil du temps.\nPour les data scientists qui travaillent avec des données ouvertes, ce projet montre l\u0026rsquo;importance de prévoir des mécanismes robustes de gestion des erreurs et d\u0026rsquo;itération sur les cas limites. La normalisation de données hétérogènes nécessite souvent des solutions empiriques adaptées à chaque contexte, plutôt que des approches standardisées.\n","date":"April 1, 2026","externalUrl":null,"permalink":"/projets/eclaireur_public/","section":"Projets","summary":"La France compte des centaines de milliers d’associations, de la petite structure locale aux organisations de plusieurs milliers de membres. Pour mener à bien leurs activités, ces associations dépendent souvent de financements publics, notamment des subventions distribuées par les collectivités locales : communes, départements, régions.\n","title":"Apporter la transparence dans les subventions publiques grâce à Eclaireur Public","type":"projets"},{"content":"Cet article est issu d’une présentation donnée dans le cadre de la formation doctorale Parcours R\u0026amp;D en entreprise à l’université Paris-Saclay. Les slides associées sont disponibles ici.\nIntroduction # En France, seuls 20% des docteurs restent dans le milieu académique. On pourrait se dire que l\u0026rsquo;on forme trop de docteurs ou que l\u0026rsquo;on ne met pas les moyens pour les intégrer. Cependant, ces réflexions occultent le fait que le doctorat apporte des compétences qui sont très prisées et utiles pour le secteur privé. L’objectif de cette présentation est de mettre en avant les atouts des docteurs, en particulier en dehors des services R\u0026amp;D des entreprises.\nLes éléments partagés ici sont des observations et des retours d’expérience personnels, liés à mon parcours. J’ai fait un doctorat à l’Université Paris Saclay (en physique des particules), puis j’ai rejoint le privé comme data scientist. J\u0026rsquo;ai évolué dans plusieurs types d\u0026rsquo;entreprises (de la startup au grand groupe) et dans différents domaines d\u0026rsquo;activité (finance, logistique, restauration). J\u0026rsquo;ai alors pu observer, dans ces contextes très différents, les enjeux des différents services au-delà de ce que l\u0026rsquo;on peut appeler la R\u0026amp;D.\nL\u0026rsquo;innovation interne # Rester compétitives oblige les entreprises à innover dans l’ensemble de leurs services : finance, organisation, opérations, expérience client, mais aussi façons de produire, de livrer et de contractualiser. L’innovation ne se limite donc pas à la R\u0026amp;D ; elle peut prendre la forme d’ajustements concrets qui réduisent les délais, diminuent les frictions et rendent les équipes plus efficaces au quotidien.\nDans cette partie, l’objectif est de montrer que l’innovation interne ressemble souvent à une série de petites révisions intelligentes. Ces changements ne sont la plupart du temps pas des découvertes, mais une application d’éléments existants dans un nouveau contexte permettant ainsi d’améliorer les performances de l’entreprise Voici quelques-uns de ces exemples.\nLe leasing comme innovation financière # Lorsqu’une entreprise veut se développer, le réflexe est souvent d’acheter le matériel nécessaire pour produire un service ou un produit. Mais acheter, c’est mobiliser immédiatement de la trésorerie et augmenter le besoin en fond de roulement : la rentabilisation de l\u0026rsquo;équipement peut arriver parfois après plusieurs semaines ou mois, et parfois plus longtemps encore.\nPour limiter ce décalage, certaines entreprises modifient leur structure financière : au lieu d’acheter l’équipement, elles le prennent en leasing, même quand elles sont propriétaires de la technologie qui permet de le fabriquer. Le leasing coûte davantage sur le long terme (intérêts), mais il reporte une grande partie de la charge au moment où le retour sur investissement commence. Concrètement, cela laisse de la marge de manœuvre au début : l’entreprise investit plus tôt dans d’autres moyens de production et vise une croissance plus soutenable. Pour une startup qui cherche à atteindre la rentabilité tout en investissant massivement, ce report de trésorerie devient un levier : elle utilise plus efficacement ses financements et réduit le risque de blocage financier.\nL\u0026rsquo;agilité pour améliorer la collaboration # Dans le développement logiciel, un problème classique est le décalage entre les besoins métiers et ce qui est réellement construit. Historiquement, on demandait au chef de projet de produire un cahier des charges, puis on transmettait aux développeurs pour implémentation. Même lorsque le document est très bon, il reste toujours des cas limites, des arbitrages implicites et des détails qui ne sont pas écrits : les échanges supplémentaires allongent alors les boucles de validation et peuvent faire diverger le produit avant le premier feedback terrain.\nL’approche agile change la logique : plutôt que de viser un gros livrable sur plusieurs mois, on travaille par séquences. On met rapidement en production une version fonctionnelle (même minimaliste), on récupère le feedback des équipes métiers, puis on itère. Cette méthode permet aussi de décider plus tôt quoi arrêter ou quoi continuer, en fonction des retours réels.\nOptimiser l\u0026rsquo;organisation d\u0026rsquo;un entrepôt # Les entrepôts ne sont pas simplement des endroits de stockage sans activité. Les équipes sont en permanence en train de circuler pour chercher, déplacer et récupérer les produits. Selon l\u0026rsquo;organisation des produits les équipes peuvent se retrouver à entrer en collision, se ralentir voire bloquer mutuellement.\nChez Foodles, l\u0026rsquo;organisation des chambres froides a subit une refonte complète pour réduire la distance parcourue par les équipes de préparation de commande et les frictions en général. D\u0026rsquo;apparence plus éclatée, avec les mêmes produits en plusieurs endroits, la nouvelle ligne de production a en pratique été pensée pour faciliter le travail des équipes qui utilisent les produits et non plus pour celles qui les stockent.\nLe design comme clé de l\u0026rsquo;usabilité # Dans la recherche, on manipule souvent des outils numériques avec des interfaces austères, voire exclusivement en ligne de commande. Mais pour la majorité des utilisateurs, l’interface est le produit : une expérience confuse ou pénible suffit à rendre une offre moins crédible, même si elle est techniquement excellente. Les designers ont donc un rôle d’innovation : rendre les parcours compréhensibles, rendre les actions évidentes, réduire la charge mentale. L’exemple le plus marquant est l’iPhone : l’interface a été repensée autour d’un modèle simple (un bouton unique, puis l’écran tactile), et a ouvert la voie à de nouvelles manières d’utiliser un téléphone. Au final, l’innovation ne concerne pas seulement la technologie : elle concerne aussi la façon dont l’utilisateur interagit avec elle.\nLes smoothies pour réduire les pertes # Les grandes surfaces jettent de grandes quantité de fruits tous les jours : des fruits moches, d\u0026rsquo;autres abimés par les palpations des clients voire juste trop approvisionnés. Souvent, ces produits restent techniquement consommables, mais ne trouvent pas preneur en rayon. C’est du gaspillage alimentaire mais aussi une perte financière pour le magasin. Une innovation simple et rentable a consisté à valoriser ces fruits sur place par la fabrications de jus ou de smoothies avec ces fruits sur le point d\u0026rsquo;être jetés. Le produit fini se vend plus cher que le fruit invendu : une ligne de perte devient une marge.\nLes compétences doctorales essentielles des entreprises # Ces quelques exemples reflètent la diversité des contextes d\u0026rsquo;innovation et des métiers. Mais lorsque l\u0026rsquo;on fait abstraction des expertises spécifiques à chacun de ces exemples (comptabilité, UX, etc.), on retrouve la nécessité d\u0026rsquo;un socle commun de compétences nécessaires au cadrage et à l\u0026rsquo;implémentation de ces solutions innovantes.\nOr il se trouve que ces compétences transversales sont justement des compétences particulièrement développées durant le doctorat.\nS\u0026rsquo;épanouir dans la complexité # L\u0026rsquo;environnement économique des entreprises évolue chaque jour et gagne en complexité. Les équipes se retrouvent à l’intersection d’enjeux et de contraintes multiples, parfois contradictoires : « faire plus avec moins » devient la norme. Pour absorber cette complexité, les organisations doivent également gagner en complexité en ajoutant des process et des outils.\nQuand la complexité devient trop élevée, certaines équipes perdent le contrôle : le système fonctionne, mais chaque nouvelle évolution ralentit les évolutions futures, voire peut introduire des erreurs graves à cause d’un angle mort. Les fuites de données de 2025 illustrent bien ce risque.\nGarder le contrôle repose sur deux idées clés :\navoir dans les équipes des personnes capables de maîtriser cette complexité, utiliser cette maîtrise pour limiter son expansion et identifier des simplifications. Les sujets data illustrent particulièrement bien ces enjeux. Les données doivent être organisées pour être mises à disposition de différentes entités, avec des objectifs différents : les utilisateurs ont besoin de leurs données, tandis que les analystes auront besoin de données agrégées. À grande échelle, cela exige aussi des infrastructures capables de traiter de gros volumes, tout en minimisant les coûts de calcul.\nDans ce contexte, des docteurs apportent une valeur immédiate. La formation à la recherche place les docteurs en permanence dans un environnement complexe. Même dans des métiers où le doctorat n’est pas \u0026ldquo;évident\u0026rdquo;, comme le développement web, on reconnaît souvent cette compétence : anticiper les effets de bord et raisonner proprement sur l’imprévu.\nLa force de l\u0026rsquo;autonomie # Dans une organisation complexe, avec un nombre croissant d’expertises différentes, il est illusoire de penser que \u0026ldquo;tout le monde\u0026rdquo; maîtrise \u0026ldquo;tout\u0026rdquo;. Les managers ne peuvent pas détailler chaque tâche ni valider chaque décision : ils n’en ont ni le temps ni, parfois, les compétences. Ils finissent donc par faire redescendre des consignes pas assez claires.\nL’autonomie devient alors une compétence très recherchée : obtenir l’information essentielle, prendre des décisions et agir dans un environnement incertain. Ce n’est pas forcément une injonction à tout faire seul : l’autonomie utile en entreprise, c’est savoir quand solliciter les bonnes personnes, et avec quelle question. Les profils autonomes réduisent l’incertitude au fil du travail, au lieu d’attendre un cadre complet.\nLa thèse place souvent les docteurs dans cette situation : un objectif de fond parfois vague, et un chemin vers le résultat qui n’est pas toujours parfaitement défini. Si l’encadrement est moins présent, il faut néanmoins trouver des manières de faire progresser le sujet. Chaque étape devient alors une action dans un contexte incertain, orientée vers un résultat.\nDe l\u0026rsquo;adaptation aux changements # L’écosystème économique est en mutation permanente. Les attentes clients évoluent. Les conventions changent. Les technologies se renouvellent vite.\nPour rester pertinentes, les entreprises doivent suivre en permanence les évolutions de leur secteur. La capacité à comprendre ces nouveautés et à estimer leur impact est alors essentielle. Elles ont besoin de profils qui vont être capables de monter rapidement en compétences sur de nouveaux outils et d\u0026rsquo;avoir un regard critique sur leurs forces et leurs limites.\nLes docteurs sont justement bien armés pour cela. La thèse développe une compétence centrale : l’autoformation. Apprendre vite sur un sujet nouveau, structurer l’information utile, puis la transformer en action concrète fait partie du cœur du travail doctoral. Pendant une thèse, il faut régulièrement explorer un domaine mal balisé, identifier les sources fiables, monter en compétence sans cadre totalement prêt, puis produire des résultats défendables. Ce réflexe est exactement celui dont les entreprises ont besoin pour suivre les évolutions technologiques et les standards métiers.\nLe besoin d\u0026rsquo;être data driven # Dans ce contexte de complexité et de changement permanent, des entreprises doivent quand même prendre des décisions sur la voie à suivre et leur transformation. Décider est souvent simple. Prendre la bonne décision est souvent plus compliqué.\nLa prise de décision dans les entreprises oscille entre deux opposés. La première est une approche qui se base sur l\u0026rsquo;expérience, l\u0026rsquo;expertise, voire simplement sur l\u0026rsquo;intuition. La seconde repose sur la recherche de données qui pourront guider la prise de décision. Beaucoup d\u0026rsquo;entreprises se vantent d\u0026rsquo;utiliser cette dernière méthode dans leur prise de décision; ce qui laisse penser que ce n\u0026rsquo;est pas une approche évidente pour tout le monde.\nCette méthode data driven est au cœur de la formation doctorale, mais sous l\u0026rsquo;appellation de méthode scientifique. Tout le concept même de la méthode scientifique (proposer des hypothèses, confronter à des données pertinentes et défendre une position devant des pairs) est au cœur du doctorat. Par définition même, les docteurs sont particulièrement pertinents dans ces positions de prise de décision.\nUn besoin de langage commun # Dans les sections précédentes, nous avons vu des compétences doctorales qui reviennent sans cesse dans les problématiques d’entreprise. Le défi, c’est que ces compétences ne sont pas toujours bien comprises par les recruteurs : en France, l’école d’ingénieur a longtemps dominé le paysage, et les chercheurs sont souvent vus comme trop abstraits. Les docteurs doivent alors traduire leur valeur en messages compréhensibles pour leurs interlocuteurs.\n\u0026ldquo;Avoir fait leurs devoirs\u0026rdquo; résume bien cet enjeu. Je l’ai entendu pendant un recrutement : l’entretien s’est arrêté rapidement, parce que je ne parlais pas la même langue que les décideurs. J’avais conscience de mes compétences, mais je n’étais pas aligné sur le cadre attendu. Quelques entretiens plus tard, pour un poste de data scientist, je n’ai pas su répondre à une question très basique : \u0026ldquo;Qu’est-ce qu’une régression logistique ?\u0026rdquo;, alors même que j’avais construit des modèles statistiques plus avancés. Le décalage venait moins du savoir que du vocabulaire et du cadre de référence attendus.\nLa gestion de projet illustre le même mécanisme : une thèse est un projet complexe mené sur plusieurs années, mais la compétence se construit sur le terrain, sans forcément être formalisée avec les méthodes et les mots standards de l’entreprise. Elle peut donc ne pas être valorisée en entretien si le candidat ne sait pas l’exprimer dans ce cadre.\nC’est pourquoi, en fin de thèse, il est essentiel de prendre du temps pour se renseigner sur les méthodologies et le vocabulaire réellement utilisés dans le privé.\nConclusion # Dans un monde toujours plus complexe et en mutation rapide, les docteurs sont un atout pour les entreprises grâce aux compétences acquises pendant leur formation. En France, ces compétences sont encore trop méconnues. C’est donc aux docteurs de faire l’effort de compréhension du mode de pensée du privé, afin de montrer l’adéquation entre leur parcours doctoral et les besoins concrets des entreprises.\n","date":"March 23, 2026","externalUrl":null,"permalink":"/conferences/2026-03-26-formation-doctorale/","section":"Conférences","summary":"Cet article est issu d’une présentation donnée dans le cadre de la formation doctorale Parcours R\u0026D en entreprise à l’université Paris-Saclay. Les slides associées sont disponibles ici.\nIntroduction # En France, seuls 20% des docteurs restent dans le milieu académique. On pourrait se dire que l’on forme trop de docteurs ou que l’on ne met pas les moyens pour les intégrer. Cependant, ces réflexions occultent le fait que le doctorat apporte des compétences qui sont très prisées et utiles pour le secteur privé. L’objectif de cette présentation est de mettre en avant les atouts des docteurs, en particulier en dehors des services R\u0026D des entreprises.\n","title":"Quelle place pour les docteurs en dehors de la R\u0026D ?","type":"conferences"},{"content":"","date":"March 14, 2026","externalUrl":null,"permalink":"/tags/duckdb/","section":"Tags","summary":"","title":"DuckDB","type":"tags"},{"content":"","date":"March 14, 2026","externalUrl":null,"permalink":"/tags/euros-for-docs/","section":"Tags","summary":"","title":"Euros for Docs","type":"tags"},{"content":"Cet article est issu d’une présentation donnée à la Holberton School à Bordeaux, puis remaniée pour une lecture continue. Les slides associées sont disponibles ici.\nL\u0026rsquo;association Data for Good # Data for Good est née d’un constat simple : la tech et ceux qui la maîtrisent servent trop souvent à optimiser des clics publicitaires. L’association a été créée pour mettre ces compétences au service du bien commun. Elle fait le lien entre des associations à forte expertise métier mais peu équipées techniquement, et des bénévoles du secteur tech qui veulent s’engager pour des causes en phase avec leurs valeurs.\nEn dix ans, Data for Good a encadré plus de 130 projets et mobilisé plus de 8 000 bénévoles. Certains ont eu un fort écho médiatique, comme Carbon Bomb, qui documente les forages pétroliers susceptibles de faire bondir les émissions de CO₂. L’association reste très active : en 2025, plus de 15 projets ont rassemblé plus de 1 000 bénévoles sur des sujets variés. Parmi les plus récents, une cartographie nationale de la qualité de l’eau du robinet, Dans Mon Eau, réalisée à partir des données publiques de relevés et d’analyses.\nData for Good n’est pas uniquement à Paris : elle se déploie progressivement dans toute la France, avec des antennes dans plusieurs villes. À Bordeaux par exemple, l’antenne organise environ un événement par mois et réunit en moyenne une vingtaine de personnes.\nLe format principal d’action de Data for Good est la saison : un hackathon de trois mois pendant lequel une douzaine d’associations présélectionnées proposent des projets à des bénévoles. Ceux-ci choisissent un sujet selon leurs valeurs, leur appétence ou le défi technique qu’ils veulent relever, et co-construisent la solution avec l’association. La saison court en général de janvier à mai. Même en dehors de cette période de hackathon, il est possible de contribuer à Data for Good.\nContrairement à un hackathon classique, les solutions ne restent pas dans un tiroir après la démo : elles sont utilisées par les associations, qui ont souvent des besoins de suivi. Les bénévoles prolongent régulièrement leur investissement auprès de l\u0026rsquo;association et en deviennent souvent membres à part entière. Les projets continuent ainsi leur activité pendant potentiellement plusieurs années même s\u0026rsquo;ils sont moins médiatisés. Pyronear en est un bon exemple : outil de détection des départs de feu en forêt à partir des images de caméras de surveillance, créé et accéléré par Data for Good, il est aujourd’hui utilisé par les pompiers. Une équipe de bénévoles continue de faire évoluer l\u0026rsquo;outil. Un des chantiers actuels consiste à améliorer la localisation des départs de feu afin de guider les pompiers vers le bon versant en vallée encaissée, ce qui permet de gagner un temps précieux. Euros for Docs fait également partie de ces projets hors saison.\nPour un projet valorisant, que ce soit dans le cadre d’un CV ou d’une fin de formation, il est possible de s’inscrire sur le site de Data for Good et de rejoindre le réseau. La plateforme recense les projets toujours en activité qui recherchent des bénévoles ; les référents peuvent être contactés afin de construire une collaboration qui réponde à la fois aux besoins de l’association et aux objectifs pédagogiques.\nEuros For Docs # À la fin des années 2000, un scandale sanitaire majeur a éclaté en France. Le Mediator, médicament vendu par les laboratoires Servier, a causé plus de 1 500 décès en trente ans et provoqué des atteintes cardiaques et pulmonaires graves chez plusieurs dizaines de milliers de personnes. Les contrôles ont révélé que les mécanismes de vérification des médicaments avaient failli, en raison de conflits d’intérêts entre Servier et les instances de contrôle. Pour y remédier, le Parlement a voté en 2011 la loi « Transparence Santé », qui oblige les laboratoires à déclarer sur une plateforme publique tout versement ou avantage accordé à un professionnel ou une association de santé. Ces données sont publiées sur data.gouv.fr pour permettre à chacun d’évaluer les conflits d’intérêts dans le secteur. La base Transparence Santé ne remplit toutefois pas pleinement ses objectifs.\nPremier problème : une recherche sur un professionnel ou une association renvoie souvent plusieurs fiches distinctes pour une même personne ou structure. Pour avoir une vision fiable des conflits d’intérêts d’un bénéficiaire, il faut donc regrouper manuellement toutes ces variantes.\nDeuxième problème : en ouvrant une fiche, on obtient surtout une liste de déclarations brutes ; pour des indicateurs agrégés (montant total, répartition par laboratoire), il faut télécharger un fichier Excel et faire soi-même l’analyse, ce qui reste peu accessible pour beaucoup de citoyens et de journalistes.\nEuros for Docs a été créée pour pallier ces deux limites et rendre la transparence sanitaire réellement exploitable. L’association poursuit deux objectifs : améliorer la qualité des données en fusionnant les variantes d’un même professionnel, et proposer sur son site un tableau de bord donnant un accès direct aux principaux indicateurs de conflits d’intérêts. Aujourd’hui, les journalistes citent en priorité Euros for Docs plutôt que Transparence Santé comme source pour ces données.\nL\u0026rsquo;infrastructure Euros For Docs # L\u0026rsquo;architecture générale du projet est représentée dans l\u0026rsquo;image suivante. Chaque jour, un job récupère sur data.gouv.fr la base Transparence Santé ainsi que d’autres sources : annuaire des professionnels de santé, annuaire des associations, et des Web API pour enrichir les adresses des déclarations. À partir de ces jeux de données, une pipeline enchaîne des requêtes SQL pour nettoyer et enrichir la base Transparence Santé et produire une base consolidée des liens financiers entre professionnels de santé et laboratoires. Cette base est envoyée vers un stockage cloud pour mise à disposition du public. Le site web la récupère chaque matin et met à jour le tableau de bord d’analyse des conflits d’intérêts proposé aux journalistes.\nUne particularité de l’infrastructure est l’usage de DuckDB. Longtemps, la data a oscillé entre deux modèles : le traitement local sur un laptop, tant que la donnée tient entièrement en RAM (sinon pandas.read_csv échoue), et le cloud, qui traite les données par morceaux entre plusieurs serveurs. Le cloud coûte cher : stockage, calcul, et expertise pour le configurer et le maintenir. Depuis quelques années émerge un troisième paradigme, souvent qualifié de « medium data » : découper un jeu trop volumineux pour la RAM en morceaux traités successivement, tout en conservant l’ensemble sur une seule machine (un seul disque dur). Pour la plupart des acteurs, les volumes ne dépassent pas quelques dizaines de téraoctets, des tailles gérables sur du matériel standard. Avec DuckDB, notre pipeline traite environ 100 Go de données sur des machines OVH peu coûteuses, avec seulement 4 Go de RAM, déjà utilisées par Euros for Docs pour héberger le site. En pratique, le pipeline ne génère donc pas de coût cloud supplémentaire.\nLa normalisation des bénéficiaires # L’un des volets les plus techniques de la pipeline concerne le nettoyage des bénéficiaires. Il s’agit d’identifier toutes les variantes d’un même bénéficiaire, de les fusionner et de les normaliser pour obtenir une base finale cohérente.\nAttribution d\u0026rsquo;un numéro interne # La première étape consiste à attribuer un identifiant unique à chaque entité que l’on considère comme une même entité réelle. Les identifiants sont au cœur de la pipeline : ils permettent d’identifier les entités et de simplifier le code en référençant un seul nombre plutôt qu’un ensemble de formulations. Nous avons analysé le jeu Transparence Santé et considérons que la combinaison (entreprise déclarante, nom, prénom, profession, code postal) désigne toujours la même entité (professionnel de santé ou association) dans le monde réel ; nous attribuons donc un numéro unique à chaque combinaison.\nTechniquement, nous utilisons une fonction de hachage qui prend en entrée une chaîne formée de ces champs et renvoie un entier en apparence aléatoire. Une même combinaison, reprise dans plusieurs déclarations, produit toujours le même entier. Une chaîne légèrement différente produit un entier différent, sans lien apparent avec les autres. Le risque est la collision : deux chaînes distinctes (par exemple à cause de coquilles) qui produiraient le même hash. En choisissant un espace de hachage bien plus grand que le nombre de combinaisons attendu, on peut considérer la probabilité de collision comme négligeable.\nUne même entité réelle peut toutefois apparaître sous plusieurs identifiants internes (par exemple noms composés déclarés différemment). Les étapes suivantes de la pipeline ont pour but de relier les comptes générés par ces variantes entre eux pour à terme les fusionner.\nCorrection de RPPS faux # À l’étape précédente, nous avons créé des identifiants internes censés cibler une seule entité. En explorant les données, nous avons constaté qu’un même compte bénéficiaire peut avoir plusieurs numéros RPPS renseignés. Le RPPS est le numéro d’identification national des professionnels de santé en France, nécessaire pour exercer. Cette situation crée un paradoxe : un identifiant interne est censé désigner un seul professionnel, mais pour un même identifiant interne on trouve plusieurs RPPS, qui, eux, désignent des personnes différentes. L’analyse montre que dans ces cas, un seul RPPS correspond vraiment aux informations déclarées (vérification via le répertoire des professionnels de santé), les autres renvoyant à des personnes sans lien (noms, prénoms ou villes différents). Nous avons mis en place une stratégie pour garder le RPPS pertinent et écarter les autres.\nConcrètement, nous comparons d’un côté les informations déclarées par l’entreprise{nom, prénom, code postal, profession) et de l’autre les informations officielles du répertoire des professionnels de santé. L’étape suivante consiste à calculer un score de similarité et à conserver le RPPS qui obtient le meilleur score. Le score combine plusieurs éléments : similarité des chaînes nom/prénom (distance de Jaro-Winkler), prise en compte des noms composés (une seule partie du nom peut être déclarée ici ou là), et des correctifs liés à la profession et au code postal. Dans l’exemple présenté, une déclaration concerne « Sandrine Amara-Allieu » mais deux RPPS sont candidats (Sandrine Allieu et Amélie Amara-Ouali) ; la seule similarité Jaro-Winkler sur le nom favoriserait le mauvais RPPS, un correctif sur les noms composés permet de retenir le bon.\nRéattribution des RPPS # Une fois corrigés les comptes avec plusieurs RPPS, il reste ceux qui n’en ont aucun. Nous utilisons à nouveau le répertoire des professionnels de santé pour retrouver une personne correspondant aux informations de la déclaration. Contrairement à l’étape précédente, le fuzzy matching est exclu : un nom et un prénom proches dans le répertoire produiraient trop de faux positifs. La méthode repose donc sur du matching exact, via une série de règles encadrées.\nLa règle la plus stricte consiste à chercher dans le répertoire une personne avec exactement le même nom, prénom, profession et code postal que la déclaration ; on peut alors lui réattribuer le RPPS. Quand la déclaration ne contient pas la profession ou le code postal, on assouplit les critères (par exemple nom + prénom + code postal uniquement). On peut alors trouver des correspondances, mais aussi des ambiguïtés : deux personnes avec le même nom dans la même ville et des métiers différents. Dans ce cas, on ne sait pas quel RPPS attribuer. Pour éviter les faux positifs, on n’attribue aucun RPPS à ce compte, en comptant sur d’autres règles ou d’autres déclarations pour le rattacher plus tard.\nLiens directs entre comptes # Il s’agit ici non pas d’attribuer un RPPS ou un SIREN à un compte, mais de repérer des comptes que nous avons créés séparément alors qu’ils désignent probablement la même entité (par exemple parce que déclarés par des entreprises différentes). Premier cas : trois comptes bénéficiaires portent le même nom d’association, un seul a un numéro SIREN, les deux autres non. Comme il n’y a aucune incohérence, on considère que ces comptes sont liés ; le SIREN pourra ensuite se propager aux deux comptes qui n’en avaient pas. Deuxième cas : même nom d’association, mais deux comptes ont un SIREN et le troisième n’en a pas ; les deux SIREN sont différents. On ne peut pas savoir lequel attribuer au troisième compte. Comme pour l’ambiguïté sur les RPPS, on ne crée pas de lien entre ces comptes : ils restent distincts pour éviter les faux positifs.\nLiens entre associations aux noms différents # Nous avons vu des cas où le nom d’association matche exactement entre déclarations et entreprises. Souvent, c’est plus complexe : les entreprises déclarent le nom comme elles veulent et produisent de nombreuses variantes pour une même entité. À l’œil humain on reconnaît la même association, mais les distances entre chaînes de caractères (ex. Jaro-Winkler) donnent des résultats très différents. Le matching exact du nom ne s’applique donc pas ; il faut une notion de similarité plus riche.\nNous avons mis en place une approche par machine learning. On découpe d’abord chaque nom d’association en trigrammes (ex. « ACTIV » → ACT, CTI, TIV) pour obtenir une liste de tokens. Cela permet d\u0026rsquo;appliquer ensuite des techniques classiques du NLP pour représenter chaque association par un vecteur. On peut alors obtenir une notion de similarité entre deux associations en comparant leurs vecteurs. On peut alors utiliser plusieurs notions de similarité pour entrainer un modèle de machine learning qui apprendra à différencier les variantes d\u0026rsquo;une même entité avec de noms d\u0026rsquo;entités différentes.\nCombinaison des règles métier # Les étapes précédentes produisent un réseau de liens entre identifiants : liens entre identifiants internes et RPPS, SIREN, RNA, ou liens directs entre comptes internes. On peut représenter tout cela sous forme de graphe (chaque nœud = un identifiant interne, RPPS, SIREN, etc. ; les arêtes = les règles métier qui les relient). On voit ainsi des blocs de comptes liés entre eux de façon plus ou moins directe, séparés du reste. Chaque bloc correspond alors à une entité réelle ; les comptes qu’il contient sont les doublons ou variantes de cette entité dans les déclarations. Certains nœuds n’avaient au départ ni RNA ni SIREN mais ont été rattachés à un bloc grâce à la similarité des noms ou au matching exact. On applique un algorithme de composantes connectées pour regrouper tous les nœuds d’un même bloc, puis on fusionne les informations pour construire une méta-entité avec les données les plus propres issues de tous ces comptes.\nLa représentation en graphe sert aussi au contrôle qualité. Certains blocs se structurent autour de plusieurs RPPS ou SIREN, ce qui témoigne d\u0026rsquo;une incohérence dans certains liens entre nœuds. Ces blocs sont marqués et ne sont pas fusionnés pour ne pas polluer la base finale. Les équipes techniques sont alertées pour analyser les règles en cause et faire évoluer le système.\nLes projets disponibles # Euros for Docs propose actuellement deux projets en collaboration avec des universités pour enrichir les données et mieux comprendre les liens d’influence chez les vétérinaires et les pharmaciens. Transparence Santé fournit surtout des liens directs : laboratoire → pharmacien (personne physique) ou laboratoire → pharmacie (entreprise). Un pharmacien peut recevoir des versements en son nom, via sa pharmacie ou via des associations dont il est membre. Ces relations transversales manquent aujourd’hui pour cartographier les stratégies d’influence multicanal.\nLors d’un séminaire nous avons repéré deux sources : le répertoire des pharmaciens avec leurs caractéristiques et les pharmacies où ils exercent, et un jeu de données sur les vétérinaires et leurs cabinets. L’objectif est de construire un jeu de liens entre bénéficiaires (par exemple lier le RPPS d’un pharmacien au SIREN de sa pharmacie) afin d’obtenir un graphe de réseau plus complet. Chaque projet comportera le traitement et l’historisation d’un jeu de données ouvert, son intégration dans Euros for Docs et du fuzzy matching pour attribuer un SIREN aux cabinets vétérinaires ou aux pharmacies à partir des informations disponibles. Ces données serviront à mettre à jour notre vision du niveau d’influence et des stratégies dans les secteurs pharmaceutique et vétérinaire.\nConclusion # Data for Good et Euros for Docs illustrent comment mettre la data au service de la transparence et du bien commun. Si vous souhaitez vous investir sur un projet concret (Euros for Docs, Pyronear ou d’autres), rejoignez Data for Good et consultez les projets ouverts aux bénévoles.\n","date":"March 14, 2026","externalUrl":null,"permalink":"/conferences/2026-03-17-holberton-eurosfordocs/","section":"Conférences","summary":"Cet article est issu d’une présentation donnée à la Holberton School à Bordeaux, puis remaniée pour une lecture continue. Les slides associées sont disponibles ici.\nL’association Data for Good # Data for Good est née d’un constat simple : la tech et ceux qui la maîtrisent servent trop souvent à optimiser des clics publicitaires. L’association a été créée pour mettre ces compétences au service du bien commun. Elle fait le lien entre des associations à forte expertise métier mais peu équipées techniquement, et des bénévoles du secteur tech qui veulent s’engager pour des causes en phase avec leurs valeurs.\n","title":"La tech pour le bien commun : le cas Euros for Docs","type":"conferences"},{"content":" data.gouv.fr et MCP : de quoi parle-t-on ? # data.gouv.fr est la plateforme française des données publiques ouvertes. Elle centralise des milliers de jeux de données (statistiques, environnement, transport, économie, etc.) et permet de les rechercher, télécharger et réutiliser. Jusqu\u0026rsquo;ici, exploiter ces données supposait de naviguer sur le site, de formuler une recherche, de parcourir les résultats puis de télécharger et traiter les fichiers localement.\nPour les profils les plus techniques, il était aussi possible d\u0026rsquo;interagir avec data.gouv.fr via des web API. Ces API permettaient d\u0026rsquo;obtenir automatiquement des listes de jeux de données ainsi que des liens de téléchargement. C\u0026rsquo;est ce que nous faisons par exemple chez Euros for Docs, en téléchargeant régulièrement les annuaires des entreprises, associations et professionnels de santé de manière automatique.\nDepuis février 2026, une expérimentation ouvre une nouvelle façon de travailler avec ces données. data.gouv.fr propose un serveur MCP (Model Context Protocol) qui permet aux assistants conversationnels (Claude, ChatGPT, Cursor, etc.) d\u0026rsquo;interroger directement le catalogue et certains jeux de données, sans quitter la conversation.\nLe Model Context Protocol (MCP) est une norme ouverte, lancée par Anthropic fin 2024 puis pilotée par la Linux Foundation. Elle décrit une façon commune de connecter un assistant conversationnel à des sources de données ou à des services en ligne. Concrètement, un serveur MCP est un programme qui met à disposition une liste d\u0026rsquo;actions bien définies, comme « rechercher des jeux de données », « ouvrir la fiche d\u0026rsquo;un dataset » ou « interroger des lignes dans un fichier tabulaire ». L\u0026rsquo;assistant (Claude, ChatGPT, Cursor, etc.) peut découvrir ces actions, les choisir et les enchaîner pour répondre à la question posée en langage naturel. Contrairement aux interfaces techniques classiques, où il faut écrire du code pour appeler tel ou tel service, le MCP permet à l\u0026rsquo;assistant de décider lui‑même quelles actions utiliser et dans quel ordre. Il fait ainsi le lien entre la conversation et des données externes, ici le catalogue et les jeux de données de data.gouv.fr.\nLe serveur MCP de data.gouv.fr est ouvert à tous et utilisable en lecture seule. On peut rechercher et consulter des jeux de données, mais pas les modifier ni en publier de nouveaux. Une fois le serveur connecté à son assistant, on pose des questions en langage naturel. Par exemple : « Quels jeux de données existent sur les prix de l\u0026rsquo;immobilier ? », « Montre‑moi les données de population pour Paris » ou « Donne‑moi un aperçu des dix premières lignes de ce fichier ». L\u0026rsquo;assistant interroge alors le catalogue data.gouv.fr, propose des jeux de données ou des ressources pertinents et peut, selon les cas, prévisualiser des extraits de données directement dans la conversation.\nDans la suite de l\u0026rsquo;article, nous allons regarder ce que cela donne concrètement sur un cas d\u0026rsquo;usage santé, puis analyser les limites et les pistes d\u0026rsquo;amélioration.\nLe cas Transparence Santé # En tant que tech lead sur le projet Euros for Docs, je voulais comprendre comment des utilisateurs de LLM pourraient interagir avec les données de transparence des liens d\u0026rsquo;intérêts dans le secteur de la santé. Après m\u0026rsquo;être connecté au serveur MCP, j\u0026rsquo;ai commencé par poser à mon agent la question suivante.\n❯ Quelles sont les données disponibles sur les risques de conflit d\u0026#39;intérêt dans la santé ? L\u0026rsquo;agent enchaîne alors plusieurs appels vers les API de data.gouv.fr. Ayant beaucoup contribué au projet Éclaireur Public, qui s\u0026rsquo;appuie aussi sur le moteur de recherche de data.gouv.fr pour trouver des jeux de données, je reconnais rapidement le schéma. L\u0026rsquo;agent teste différents mots‑clés dans le moteur de recherche. Une première requête sur conflit+interet+sante ne renvoie aucun résultat. Une deuxième tentative sur transparence+sante+liens+interet n\u0026rsquo;est pas plus fructueuse. Finalement, une recherche plus simple sur transparence+sante renvoie des jeux de données pertinents.\nOn remarquera d\u0026rsquo;ailleurs que j\u0026rsquo;avais fais exprès de ne pas mettre le mot transparence dans ma question mais que l\u0026rsquo;agent a naturellement testé un synonyme.\nUne requête spécifique sur la page dédiée à Transparence Santé (via l\u0026rsquo;API https://www.data.gouv.fr/api/1/datasets/transparence-sante-1/) permet ensuite à l\u0026rsquo;agent de récupérer les informations essentielles et de proposer une synthèse du jeu de données.\ntitle: \u0026#34;Etude de cas du MCP server de data.gouv\u0026#34; date: 2026-03-03T08:24:53+02:00 draft: true description: \u0026#34;Présentation du serveur MCP de data.gouv.fr : concept de MCP, intégration dans un agent LLM et exemples d\u0026#39;usage pour interroger les données publiques depuis un assistant conversationnel.\u0026#34; --- ## Introduction **[data.gouv.fr](https://www.data.gouv.fr/)** est la plateforme française des données publiques ouvertes. Elle centralise des milliers de jeux de données (statistiques, environnement, transport, économie, etc.) et permet de les rechercher, télécharger et réutiliser. Pour qui souhaite exploiter ces données, le parcours classique consiste à passer par le site, formuler une recherche, parcourir les résultats puis télécharger et traiter les fichiers localement. Pour les profils les plus techniques, il était également possible d\u0026#39;intéragir avec data.gouv à travers des web API. Ces API permettaient d\u0026#39;obtenir automatiquement des listes de jeux de données ainsi que des liens de téléchargement. C\u0026#39;est ce que nous faisons chez [Euros For Docs](../../projets/eurosfordocs/) en téléchargeant régulièrement les annuaires des entreprises, associations et professionnels de santé de manière automatique. Depuis février 2026, une **expérimentation** propose une autre voie : un serveur **MCP** (Model Context Protocol) qui permet aux assistants conversationnels (Claude, ChatGPT, Cursor, etc.) d’interroger data.gouv.fr directement depuis la conversation. Le **Model Context Protocol** (MCP) est une norme ouverte, lancée par Anthropic fin 2024 puis pilotée par la Linux Foundation, qui décrit une façon commune de connecter un assistant conversationnel à des sources de données ou à des services en ligne. Concrètement : un **serveur MCP** est un programme qui met à disposition une liste d’actions bien définies (rechercher des jeux de données, ouvrir une fiche, interroger des lignes, etc.) ; l’assistant (Claude, ChatGPT, Cursor…) peut alors découvrir ces actions et les enchaîner tout seul pour répondre à la question posée. Contrairement aux interfaces techniques classiques, où il faut écrire du code pour appeler tel ou tel service, le MCP permet à l’assistant de choisir lui-même quelles actions appeler et dans quel ordre, à partir d’une question en langage naturel. Il fait ainsi le lien entre la conversation et des données externes — ici, le catalogue et les jeux de données de data.gouv.fr. Le **serveur MCP de data.gouv.fr** est [ouvert à tous](https://github.com/datagouv/datagouv-mcp) et utilisable en lecture seule : on peut rechercher et consulter des jeux de données, pas les modifier ni en publier. Une fois le serveur connecté à son assistant (Claude, ChatGPT, Cursor, etc.), on pose des questions en langage naturel. Par exemple : *« Quels jeux de données existent sur les prix de l’immobilier ? »*, *« Montre-moi les données de population pour Paris »* ou *« Donne-moi un aperçu des dix premières lignes de ce fichier »*. L’assistant interroge alors le catalogue data.gouv.fr, propose des jeux de données ou des ressources pertinents et peut, selon les cas, prévisualiser des extraits de données directement dans la conversation. L’article qui suit détaille le fonctionnement de ce serveur et des exemples d’usage concrets. ## Le cas Transparence santé En tant que tech lead sur le projet Euros for Docs, j\u0026#39;ai voulu savoir comment les utilisateurs des LLM pourraient interagir avec nos données. Après m\u0026#39;être connecté au mcp j\u0026#39;ai commencé par demander à mon agent : ```bash ❯ Quelles sont les données disponibles sur les risques de conflit d\u0026#39;intérêt dans la santé? S\u0026rsquo;ensuit une liste d\u0026rsquo;appels vers les API data for good. Ayant beaucoup contribué au projet Eclaireur Public dans lequel nous recherchions des jeux de données sur les subventions octroyées par les communes, je comprend que l\u0026rsquo;agent utilise le moteur de recherche de data.gouv pour chercher des jeux de données. Après une première recherche des termes conflit+interet+sante qui ne donne aucun résultat, une deuxième avec les termes transparence+sante+liens+interet ne trouve pas plus de résultats. Finalement une requête sur les termes transparence+sante donnent enfin des résultat et une requete spécifiquement sur la page web dédiée à Transparence Santé (https://www.data.gouv.fr/api/1/datasets/transparence-sante-1/) permet à l\u0026rsquo;agent de récupérer les informations essentielles de ce jeu de données et proposer une description.\nVoici les données disponibles sur data.gouv.fr concernant les risques de conflit d\u0026#39;intérêt dans la santé : --- Transparence-Santé Jeu de données principal : transparence-sante-1 Organisation : Ministère des Solidarités et de la Santé (certifié) Description Base de données publique qui recense les liens entre les entreprises du secteur sanitaire et les acteurs de la santé. Conformément aux articles L. 1453-1 et L. 1453-2 du code de la santé publique, les entreprises produisant ou commercialisant des produits sanitaires ou cosmétiques doivent déclarer : - Les conventions passées avec les professionnels de santé - Les rémunérations versées - Les avantages accordés (cadeaux, invitations, etc.) Caractéristiques ┌─────────────┬───────────────────────────────────────────────────────────────────────────┐ │ Élément │ Détail │ ├─────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Volume │ + de 10 millions de lignes │ ├─────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Format │ CSV │ ├─────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Mise à jour │ Quotidienne │ ├─────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Licence │ CC BY-NC-SA 4.0 (non commercial) │ ├─────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Couverture │ France entière │ ├─────────────┼───────────────────────────────────────────────────────────────────────────┤ │ Source │ Déclarations semestrielles des entreprises via transparence.sante.gouv.fr │ └─────────────┴───────────────────────────────────────────────────────────────────────────┘ Tags associés avantage, convention, médecin, médicament, professionnels de santé, transparence --- C\u0026#39;est le principal jeu de données disponible sur data.gouv.fr pour ce sujet. Il s\u0026#39;agit de l\u0026#39;équivalent français du Sunshine Act américain, conçu pour prévenir les conflits d\u0026#39;intérêt entre l\u0026#39;industrie pharmaceutique/cosmétique et les professionnels de santé. Les données permettent de vérifier si un médecin ou un établissement a reçu des avantages de la part d\u0026#39;entreprises du secteur. Alors qu\u0026rsquo;Euros for Docs est bien identifié dans le domaine de la santé pour proposer une base de données enrichie à partir de Transparence Santé, l\u0026rsquo;agent ne le mentionne pas du tout. Cela s\u0026rsquo;explique par la manière dont le serveur MCP voit les données. Sur data.gouv.fr, Euros for Docs n\u0026rsquo;apparaît que comme une réutilisation du jeu de données Transparence Santé. Les fichiers enrichis ne sont accessibles qu\u0026rsquo;à travers un lien dans la description de cette réutilisation. Dans la réponse de l\u0026rsquo;API, les réutilisations ne sont pas exposées. Le serveur MCP et l\u0026rsquo;agent n\u0026rsquo;ont donc tout simplement pas de moyen direct de découvrir Euros for Docs.\nDans la suite de l\u0026rsquo;analyse, l\u0026rsquo;agent va donc travailler uniquement à partir des données brutes de Transparence Santé, sans bénéficier des enrichissements réalisés par Euros for Docs. Cela pose la question de la qualité effective des résultats produits par un agent branché sur ce serveur MCP.\nQuel accès aux données de Transparence Santé ? # On peut explorer les possibilités d’analyse des données de Transparence Santé qui sont exposées par le serveur MCP, et ce même si nous n’avons pas accès aux données enrichies d’Euros for Docs.\nPour ce deuxième test, je pose la question suivante à l’agent :\nDonne moi le montant recu par ASSOCIATION CLINIQUE ET THÉRAPEUTIQUE INFANTILE DU VAL DE MARNE en fonction de l\u0026#39;entreprise distributrice. Cette association est représentative des problèmes de qualité de données que l\u0026rsquo;on rencontre dans Transparence Santé. Elle apparaît dans les déclarations sous de nombreuses variantes. Une étude de cas d\u0026rsquo;Euros for Docs lui a d\u0026rsquo;ailleurs été dédiée.\nDans un premier temps, l\u0026rsquo;agent tente d\u0026rsquo;interroger directement l\u0026rsquo;API Transparence Santé, mais échoue à cause d\u0026rsquo;une URL incorrecte. Il envisage alors de télécharger le fichier CSV complet pour l\u0026rsquo;analyser localement. Le fichier pesant environ 460 Mo, cette solution est abandonnée, et l\u0026rsquo;agent revient à l\u0026rsquo;API Transparence Santé avec une URL corrigée.\nAprès un appel général pour comprendre le schéma de l\u0026rsquo;API, l\u0026rsquo;agent lance une nouvelle requête en demandant explicitement les déclarations dont le champ d\u0026rsquo;identité du bénéficiaire correspond exactement au nom de l\u0026rsquo;association que nous avons indiqué.\nhttps://www.transparence.sante.gouv.fr/api/explore/v2.1/catalog/datasets/declarations/records?where=identite%20like%20%22CLINIQUE%20ET%20THERAPEUTIQUE%20INFANTILE%22\u0026amp;limit=100\u0026amp;select=raison_sociale%2Cmontant%2Clien_interet%2Cdate%2Cidentite Après analyse des résultats de cette API, l\u0026rsquo;agent me propose la synthèse suivante.\nAlors qu\u0026#39;Euros for Docs est connu dans le domaine de la santé pour fournir une base de données enrichie par rapport à Transparence Santé, ici seule cette dernière est connue. Comprenant le fonctionnement du mcp et les actions prises par l\u0026#39;agent, cela est tout à fait cohérent. Sur data.gouv, Euros for docs n\u0026#39;existe qu\u0026#39;à travers une mention dans les réutilisations de la base transparence santé. Les données EurosFordocs ne sont elles que mentionnées dans un lien dans la description de la réutilisation. En regardant le résultat de l\u0026#39;appel api de la page transparence santé, nous ne voyons aucune mention des réutilisations, d\u0026#39;où l\u0026#39;invisibilité d\u0026#39;EurosForDocs. L\u0026#39;utilisation de l\u0026#39;interface de MCP data.gouv pour l\u0026#39;analyse des conflits d\u0026#39;intérêts va donc se baser sur des données de qualité discutable. ## Quel accès aux données de transparence? ne pas avoir accès à Euros for docs est dommage mais regardons la manière dont nous pouvons interagir avec les données de transparence. J\u0026#39;ai alors posé la question suivante : Donne moi le montant recu par ASSOCIATION CLINIQUE ET THÉRAPEUTIQUE INFANTILE DU VAL DE MARNE en fonction de l\u0026rsquo;entreprise distributrice.\nCette association est représentative des problématiques de qualité de données que nous pouvons avoir sur Transparence Santé. Les entreprises sont plutôt créatives pour renseigner le nom de cette association dans les déclarations. Une [étude de cas](https://eurosfordocs.fr/case_activ) a été publiée par Eurosfor docs sur cette association. Après un premier échec (du fait d\u0026#39;une mauvaise url) pour reqêter la base transparence santé via api, mon agent a souhaité télécharger le fichier complet en local pour l\u0026#39;analyser. Le fichier CSV faisant 460Mb, l\u0026#39;agent a décidé de retenter les appels API sur le site transparence santé. Après un appel général pour comprendre le schéma l\u0026#39;API, l\u0026#39;agent lance une nouvelle requête api en demandant explicitement les déclarations dont l\u0026#39;identité du bénéficiaire est exactement le nom que nous avons mentionné. https://www.transparence.sante.gouv.fr/api/explore/v2.1/catalog/datasets/declarations/records?where=identite%20like%20%22CLINIQUE%20ET%20THERAPEUTIQUE%20INFANTILE%22\u0026limit=100\u0026select=raison_sociale%2Cmontant%2Clien_interet%2Cdate%2Cidentite\nAprès analyse des résultats de cette API, l\u0026#39;agent me propose cette réponse. ```markdown Les 21 enregistrements sont bien tous récupérés. Voici le récapitulatif complet : --- Montants reçus par l\u0026#39;ASSOCIATION CLINIQUE ET THÉRAPEUTIQUE INFANTILE DU VAL DE MARNE (ACTI) Par entreprise ┌─────────────────────────────┬───────────────┬────────────────────┐ │ Entreprise │ Montant total │ Nb de déclarations │ ├─────────────────────────────┼───────────────┼────────────────────┤ │ LABORATOIRE GLAXOSMITHKLINE │ 314 637 € │ 8 │ ├─────────────────────────────┼───────────────┼────────────────────┤ │ MSD FRANCE │ 332 018 € │ 12 │ ├─────────────────────────────┼───────────────┼────────────────────┤ │ MEDICAL AXES │ Non chiffré │ 1 │ ├─────────────────────────────┼───────────────┼────────────────────┤ │ TOTAL │ ~646 655 € │ 21 │ └─────────────────────────────┴───────────────┴────────────────────┘ Détail par type de lien et entreprise LABORATOIRE GLAXOSMITHKLINE : ┌──────────────┬──────────┬────────────┐ │ Type │ Montant │ Date │ ├──────────────┼──────────┼────────────┤ │ Convention │ 20 000 € │ 2020-12-04 │ ├──────────────┼──────────┼────────────┤ │ Convention │ 30 000 € │ 2020-12-04 │ ├──────────────┼──────────┼────────────┤ │ Convention │ 20 000 € │ 2022-01-10 │ ├──────────────┼──────────┼────────────┤ │ Convention │ 30 000 € │ 2022-01-10 │ ├──────────────┼──────────┼────────────┤ │ Rémunération │ 24 000 € │ 2022-01-25 │ ├──────────────┼──────────┼────────────┤ │ Rémunération │ 36 000 € │ 2022-01-25 │ ├──────────────┼──────────┼────────────┤ │ Convention │ 60 037 € │ 2022-06-01 │ ├──────────────┼──────────┼────────────┤ │ Convention │ 43 000 € │ 2022-10-04 │ ├──────────────┼──────────┼────────────┤ │ Rémunération │ 51 600 € │ 2022-11-29 │ └──────────────┴──────────┴────────────┘ MSD FRANCE : ┌──────────────┬──────────┬────────────┐ │ Type │ Montant │ Date │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 30 018 € │ 2024-09-04 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 50 000 € │ 2024-09-04 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 30 000 € │ 2024-09-04 │ ├──────────────┼──────────┼────────────┤ │ Convention │ 72 000 € │ 2025-01-10 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 20 000 € │ 2025-02-10 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 15 000 € │ 2025-06-25 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 15 000 € │ 2025-06-25 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 50 000 € │ 2025-07-01 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 15 000 € │ 2025-08-04 │ ├──────────────┼──────────┼────────────┤ │ Avantage │ 15 000 € │ 2025-08-04 │ ├──────────────┼──────────┼────────────┤ │ Rémunération │ 20 000 € │ 2025-09-10 │ └──────────────┴──────────┴────────────┘ MEDICAL AXES : ┌────────────┬──────────────┬────────────┐ │ Type │ Montant │ Date │ ├────────────┼──────────────┼────────────┤ │ Convention │ Non spécifié │ 2019-11-13 │ └────────────┴──────────────┴────────────┘ --- Observations : - Les liens avec GlaxoSmithKline sont concentrés sur 2020-2022, principalement sous forme de conventions et rémunérations - Les liens avec MSD France sont plus récents (2024-2025) et composés majoritairement d\u0026#39;avantages - Le montant total déclaré avoisine les 650 000 € sur la période couverte Quelle qualité en pratique ? # À ce stade, la réponse de l\u0026rsquo;agent est cohérente avec les données qu\u0026rsquo;il a récupérées. Mais si l\u0026rsquo;on compare ces chiffres avec ceux récupérés à la main sur Transparence Santé et Euros for Docs comme dans l\u0026rsquo;étude de cas ACTIV, les écarts sont très importants. Il est à noter que les résultats évoluant au fil des déclarations, les chiffres présentés dans cet article seront surement déjà obsolètes au moment de la lecture.\nLa principale source de différence vient de l\u0026rsquo;utilisation du nom exact de l\u0026rsquo;association pour filtrer les déclarations. En pratique, les entreprises ne renseignent pas toujours cette association avec ce nom exact. Elles peuvent par exemple omettre une partie du nom, utiliser un sigle, faire une faute de frappe ou inverser certains termes. Pour limiter ces problèmes, Euros for Docs recommande d\u0026rsquo;utiliser le SIREN pour identifier les bénéficiaires personnes morales.\nUn utilisateur ou une utilisatrice sans bagage technique n\u0026rsquo;a pas forcément ce réflexe. En revanche, un agent pourrait l\u0026rsquo;avoir si les API étaient mieux documentées, ou si les jeux de données fournissaient des exemples de bonnes pratiques. Pour tester cette idée, j\u0026rsquo;ai donc demandé explicitement à l\u0026rsquo;agent de commencer par retrouver le SIREN de l\u0026rsquo;association, puis de l\u0026rsquo;utiliser pour extraire les déclarations pertinentes.\nÀ travers une recherche internet et un appel à l\u0026rsquo;API recherche-entreprises.api.gouv.fr, exposée via le serveur MCP de data.gouv.fr, l\u0026rsquo;agent retrouve bien le numéro SIREN de l\u0026rsquo;association, 380061887. En se basant sur ce SIREN, il parvient ensuite à reconstituer exactement l\u0026rsquo;ensemble des déclarations que l\u0026rsquo;on obtient en effectuant une recherche manuelle dans l\u0026rsquo;interface de Transparence Santé.\n# déclarations montant total Recherche TS manuelle 172 20 651 326 Recherche EFD manuelle 208 17 834 911 Agent via MCP (nom exact) 21 646 655 Agent via MCP (guidé SIREN) 172 20 651 326 Ces résultats montrent deux choses importantes. D\u0026rsquo;abord, un agent LLM connecté au serveur MCP peut retrouver des résultats fiables, proches d\u0026rsquo;une recherche experte, à condition d\u0026rsquo;être suffisamment guidé. Ensuite, le MCP ne règle pas à lui seul les problèmes de qualité ou de modélisation des données. La manière dont les jeux de données sont décrits, structurés et documentés reste déterminante pour la qualité des réponses produites.\nQuelles pistes d\u0026rsquo;amélioration ? # Une première piste serait d\u0026rsquo;intégrer plus directement les données d\u0026rsquo;Euros for Docs dans l\u0026rsquo;écosystème de data.gouv.fr. Par exemple, les jeux de données enrichis pourraient être mieux mis en avant, avec une description qui explique clairement leurs apports par rapport à Transparence Santé. Les agents auraient ainsi la possibilité de privilégier, lorsque c\u0026rsquo;est pertinent, ces jeux de données enrichis pour répondre aux questions des utilisateurs.\nOn se heurterait toutefois à une autre contrainte, déjà visible avec Transparence Santé. Les fichiers complets sont volumineux et difficiles à manipuler dans le contexte d\u0026rsquo;un agent LLM. De la même manière que pour Transparence Santé, il serait donc utile que les données d\u0026rsquo;Euros for Docs soient exposées via une API adaptée aux requêtes ciblées. Aujourd\u0026rsquo;hui, les utilisateurs humains sont redirigés vers notre Metabase pour explorer les données. À terme, les agents devraient pouvoir interagir eux aussi avec ce type d\u0026rsquo;interface analytique, via des points d\u0026rsquo;entrée pensés pour eux.\nEnfin la solution la plus simple serait que Transparence Santé améliore sa qualité de données pour bénéficier des interfaces qui fonctionnent déjà très bien.\nConclusion # Le serveur MCP de data.gouv.fr marque une étape utile dans l’ouverture des données publiques aux usages conversationnels. Il permet à un assistant d’identifier des jeux de données, d’en résumer le contenu et, dans certains cas, d’interroger directement des données tabulaires. Des personnes peu familières avec les API ou les outils data peuvent ainsi commencer à poser des questions complexes et à explorer les données de transparence sans écrire une ligne de code.\nCette ouverture s’accompagne toutefois de limites, illustrées par le cas Transparence Santé. Dès que l’on touche à la qualité des données, à leur modélisation ou aux besoins d’enrichissement, les réponses de l’agent dépendent fortement de la façon dont les jeux de données sont décrits et exposés. Pour que ces outils servent réellement aux enquêtes sur les conflits d’intérêts, il faudra faire évoluer à la fois les jeux de données et les interfaces qui les exposent. Les producteurs de données ouvertes devront sans doute adapter leurs catalogues, leurs API et leurs descriptions pour qu’ils soient plus facilement utilisables par des agents, à l’image des entreprises qui commencent à se préoccuper de leur présence dans les résultats des assistants de recherche.\nQuelle qualité en pratique? # Lorsque nous comparons le résultat fourni par l\u0026rsquo;agent avec celui proposé dans l\u0026rsquo;étude de cas ACTIV, nous obtenons des résutlats très divergents par rapport aux 2 systèmes déjà proposés dans l\u0026rsquo;étude.\nLa première source de différence vient de l\u0026rsquo;utilisation du nom exact de l\u0026rsquo;associaiton pour trouver les déclarations. Les entreprises utilisant différents noms, nous recommandons d\u0026rsquo;utiliser le siren pour identifier les bénéficiaires personne morale. Bien sur les utilisateurs non tech n\u0026rsquo;ont pas nécessairement ce réflexe mais une amélioration de la description de l\u0026rsquo;API transparence santé pourrait inciter un agent à le faire automatiquement. J\u0026rsquo;ai donc testé en demandant explicitement à l\u0026rsquo;agent de trouver le siren de l\u0026rsquo;association (via jeux de données siren également disponible dans data.gouv et accessible via MCP) et d\u0026rsquo;utiliser ce siren pour extraire des déclarations.\nA travers une recherche internet et l\u0026rsquo;appel à l\u0026rsquo;api recherche-entreprises.api.gouv.fr fournie par le MCP l\u0026rsquo;agent retrouve bien le numéro siren de l\u0026rsquo;association : 380061887. A partir de cette information, l\u0026rsquo;agent retrouve bien exactement les données qui que l\u0026rsquo;on pouvait retrouver en faisant une recherche manuelle à partir du siren.\n|-|-|-|\n# déclaration montant total Recherche TS manuelle 172 20 651 326 Recherche EFD manuelle 208 17 834 911 Agent simple 21 646 655 Agent guidé siren 172 20 651 326 - - - Ces résultats montrent que le MCP n\u0026rsquo;est pas suffisant pour permettre à des utilisateurs qui ne connaissent pas les données. Il est aussi nécessaire pour les fournisseurs de données d\u0026rsquo;adapter leur définition des datasets pour s\u0026rsquo;adapter à ces nouveaux utilisateurs : les agents.\nQuelles solutions # L\u0026rsquo;ajout de serveur MCP data.gouv permet d\u0026rsquo;ouvrir de nouveaux usagers aux données de transparence. Il est donc important d\u0026rsquo;accompagner ces utilisateurs, potentiellement involontaires, vers des données fiables et de qualité. Un axe d\u0026rsquo;amélioration serait d\u0026rsquo;intégrer directement les données Euros for docs aux jeux de données référencés par data.gouv, et via une description du jeu de données, orientier les agents qui auront le choix du dataset à prioriser le dataset eurosfordocs. Mais nous feront à nouveau face à la problématique d\u0026rsquo;un fichier de taille importante à traiter pour l\u0026rsquo;agent. De manière similaire à transparence santé, il faudrait que les données de EurosForDocs soient accessible via API. Tout comme les utilisateurs sont redirigés vers notre metabase pour explorer, les agents devraient pouvoir intéragir avec metabase pour requeter des données.\nconclusion # La création de ce serveur MCP de data.gouv peut déclencher de changements majeurs sur l\u0026rsquo;utilisation des données ouvertes. Tout comme les entreprises s\u0026rsquo;intéressent au GEO pour s\u0026rsquo;assurer de la publicité de leur offre via les agents, les fournisseurs de données vont peut-être devoir s\u0026rsquo;adapter également.\n","date":"March 4, 2026","externalUrl":null,"permalink":"/articles/mcp_data_gouv/","section":"Articles","summary":"data.gouv.fr et MCP : de quoi parle-t-on ? # data.gouv.fr est la plateforme française des données publiques ouvertes. Elle centralise des milliers de jeux de données (statistiques, environnement, transport, économie, etc.) et permet de les rechercher, télécharger et réutiliser. Jusqu’ici, exploiter ces données supposait de naviguer sur le site, de formuler une recherche, de parcourir les résultats puis de télécharger et traiter les fichiers localement.\n","title":"Serveur MCP de data.gouv : ce qui change pour l’accès aux données publiques, et ce qui reste à faire","type":"articles"},{"content":"","date":"10 January 2026","externalUrl":null,"permalink":"/en/conferences/","section":"Conferences","summary":"","title":"Conferences","type":"conferences"},{"content":"","date":"10 January 2026","externalUrl":null,"permalink":"/en/","section":"Data Diffusion","summary":"","title":"Data Diffusion","type":"page"},{"content":"Presentation given as part of the Bordeaux ApérOps meetup on February 11, 2026.\nDownload slides (PDF)\nThe stakes of transparency in healthcare # The Mediator scandal # Mediator is a drug derived from amphetamine, marketed by the Servier laboratory as an antidiabetic from 1976. Beyond its official framework of use, it was however massively prescribed as an appetite suppressant for more than thirty years. During all these years, it is said to have caused the death of more than 1,500 people and created serious illnesses in thousands of others.\nThe scandal broke in 2009 when pulmonologist Irène Frachon published the book Mediator 150 mg: How many deaths?.\nTransparence Santé # Following this scandal which had highlighted conflicts of interest in oversight bodies, a law was passed to require pharmaceutical companies to declare all remuneration or benefit in kind provided to healthcare professionals or any other actor related to health (associations, companies). All these declarations were made available to the public through an open data platform Transparence Santé.\nA murky transparency # While transparency can be considered achieved through data availability, the objective has not been reached. Poor data quality, mainly lack of normalization and duplicates, make data exploitation very complicated for anyone without data skills.\nA simple search for a treating physician can quickly turn into a headache. The example below shows that multiple beneficiaries each appear multiple times. The maximum we see here is 3 duplicates but it\u0026rsquo;s possible to have several dozen for hospitals or other associations with complex names.\nThe difficulties persist when interested in a particular beneficiary account. The interface only allows us to see a list of declarations without any way to aggregate amounts for example. When the account benefits from many declarations, it becomes unmanageable for a person without data management knowledge to have a comprehensive and reliable view of conflicts of interest risks.\nData quality as the basis for transparency # The EurosForDocs association # EurosForDocs was then created to resolve these issues and transform the Transparence Santé database into a real tool for combating conflicts of interest. The association is organized around 3 main objectives:\ndata cleanup, particularly merging duplicates; making data available in an interactive and intuitive dashboard; supporting journalists, researchers and citizens in data exploitation. The road to beneficiary unification # The need for reliable identifiers # When manipulating data where the same entity can appear multiple times, it\u0026rsquo;s always preferable to assign an identification number to each identity. This way, it\u0026rsquo;s easy to select only the data related to a specific entity using this identifier. On Transparence Santé, it would be practical to have a unique identifier for a beneficiary, regardless of declaration errors that companies might make.\nIndeed, the administration long ago found a solution to this problem. Healthcare professionals with the right to practice in France must register and are assigned a national identifier: the RPPS. Similarly, any company or association must register and receive respectively a SIREN number or an RNA number (or both).\nIn theory, laboratories have all the information to create a clean and well-structured dataset. Unfortunately, declaring companies don\u0026rsquo;t use them systematically. On the contrary, nearly 50% of declarations concerning legal entities do not declare a SIREN or RNA number. This means that nearly 500 million euros of influence cannot be easily attributed to an institution.\nThe main challenge for EurosForDocs is therefore to try to reassign one of these national identifiers to each beneficiary in the database.\nIndexing beneficiaries # When companies don\u0026rsquo;t declare a national identifier, no other identifier (even an internal one) is created. So a company can declare additional remuneration to an entity but name it differently. The phenomenon is amplified if this entity also receives remuneration from other companies. In the end, you can have multiple mentions, potentially very different, of the same entity without an explicit link between them.\nOur beneficiary deduplication strategy then organizes into two stages. First we create a unique identifier for each declared variant of beneficiaries. Through data exploration, we decided that a company declaring the same (name, first name, profession, postal_code) twice refers to the same entity. We then use a hash function that transforms this combination of characteristics into a random integer specific to this combination. This integer will serve to uniquely identify a beneficiary account. This article presents hash functions in more detail in another use case.\nOnce we have defined our beneficiary accounts, we will seek to clean them and then identify all accounts that refer to the same entity so that, ultimately, we can merge them.\nCleaning inconsistent RPPS # When we defined the information that defined a beneficiary account, we observed that for the same combination of (name, first name, profession, postal_code), some companies could add different modes of identification. For example, one declaration would contain the RNA number and another the SIREN number. We therefore decided to keep this diversity within a beneficiary account.\nHowever, it regularly happens that for healthcare professionals, two distinct RPPS numbers are present in the same beneficiary account. After detailed analysis of these cases, we observed that only one RPPS is consistent with the other declared information and that the other numbers correspond to very different professionals.\nOur objective being to merge beneficiaries around an RPPS number, we must ensure that each beneficiary account is internally consistent. Through the healthcare professionals directory, we can obtain official information linked to an RPPS number. A scoring system (fuzzy matching) between declared information and official information for each RPPS allows us to estimate the consistency between official and declared information, and keep only the most relevant RPPS number.\nRPPS assignment # Many declarations don\u0026rsquo;t have the luxury of having even a single RPPS number. We then seek to link the information documented by the company with a healthcare professional from the directory. We first look for an exact match on name, first name, profession and postal code. We add to this logic mechanisms to handle the case of compound names for which only part might be entered, or the order inverted.\nMany declarations have missing or incorrect information, which makes the first step ineffective for finding an RPPS. We then test unidentified beneficiary accounts with looser constraints, for example not considering the postal code. By relaxing constraints, the risk of hitting homonyms increases. We only assign an RPPS if there is only one healthcare professional corresponding to the constraints.\nAssign direct links # Once we have assigned as many RPPS identifiers as possible to beneficiaries, we will seek to directly identify links between accounts. We hope that accounts without RPPS can obtain one indirectly. Likewise, we hope that legal entity accounts, for which we have no mechanism to find the SIREN, can obtain one.\nSimilar to the creation of beneficiary accounts, we group accounts by (name, first name, postal code and profession). If the group brings together multiple distinct SIREN (or RNA or RPPS) numbers, we consider this information to refer to multiple distinct entities (potentially due to declaration errors) and do nothing. Otherwise, we create a link between all these accounts to consider them as belonging to the same entity. Link associations through machine learning # Unlike healthcare professionals for whom there are relatively few possible variations (apart from compound names), associations (or legal entities in general) can be named very differently while maintaining clarity of the targeted entity. This EurosForDocs case study explores a particular case.\nWe therefore seek to identify whether two potentially very different names (from the perspective of standard string similarity measures) refer to the same entity. To obtain elements to compare between the two names, we apply a method called shingles. The idea is to break down our association name into all combinations of 3 consecutive letters. The association name is then transformed into a sentence where elements are not words but our trigrams. From this new representation of each name, we can apply standard natural language techniques (NLP) to evaluate the similarity between the two names. Finally, a machine learning model will use the different notions of similarity and determine the best way to combine them to identify pairs of names from the same entity.\nMerging accounts # At this level of data processing, beneficiary accounts can be linked to one or multiple national identifiers but also to one or multiple other accounts. To recreate a beneficiary entity, we represent all accounts and relationships in graph form. This representation allows us to use an algorithm to group all beneficiary accounts linked to each other, even indirectly. Each of these blobs is then interpreted as an entity. Accounts belonging to the entity will be merged and the aggregated information from the entity will serve to normalize beneficiary information in declarations. For more details on account merging, see this dedicated article\nStill for data quality reasons, it can happen that multiple SIRENs (or RPPS, RNA) are present in the same blob. A national identifier must identify an entity uniquely, so this situation informs us that one or more links in our database are false and group accounts corresponding to separate entities. We are able to easily identify these situations (if not fix them) and we prevent account merging belonging to these blobs. This is why in practice, beneficiary accounts for university hospitals are rarely merged because there is always a declaration to introduce a wrong SIREN or the RNA of an association.\nWithout data quality, transparency is a myth # This EurosForDocs cleanup work significantly improves the quality of Transparence Santé data. The ability to uniquely and accurately identify a healthcare professional (and soon an association) greatly facilitates the work of journalists and citizens, as evidenced by numerous collaborations in article writing.\n","date":"10 January 2026","externalUrl":null,"permalink":"/en/conferences/2026-02-11-aperops-eurosfordocs/","section":"Conferences","summary":"Presentation given as part of the Bordeaux ApérOps meetup on February 11, 2026.\nDownload slides (PDF)\nThe stakes of transparency in healthcare # The Mediator scandal # Mediator is a drug derived from amphetamine, marketed by the Servier laboratory as an antidiabetic from 1976. Beyond its official framework of use, it was however massively prescribed as an appetite suppressant for more than thirty years. During all these years, it is said to have caused the death of more than 1,500 people and created serious illnesses in thousands of others.\n","title":"EurosForDocs: Strengthening Healthcare Transparency Through Data Quality","type":"conferences"},{"content":"","date":"16 December 2025","externalUrl":null,"permalink":"/en/articles/","section":"Articles","summary":"","title":"Articles","type":"articles"},{"content":"","date":"16 December 2025","externalUrl":null,"permalink":"/en/tags/data-engineering/","section":"Tags","summary":"","title":"Data Engineering","type":"tags"},{"content":"","date":"16 December 2025","externalUrl":null,"permalink":"/en/tags/sql/","section":"Tags","summary":"","title":"Sql","type":"tags"},{"content":"","date":"16 December 2025","externalUrl":null,"permalink":"/en/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"As a data engineer, we are not always masters of our data sources. Particularly when using open data, we are at the mercy of the changes made by data producers.\nAs part of the Euros For Docs project, our primary data source is the Transparence Santé database. This file published daily contains more than 8 million declarations of remuneration from healthcare professionals or health associations by pharmaceutical companies. From one day to the next, the file undergoes many changes: new declarations are added, some disappear and others are simply modified.\nFiles that change daily # To track the evolution of declarations, we want to create a historical file containing all versions of the declarations. Using a unique identifier for each declaration provided in the file, we are able each day to compare a declaration with its last historical value and identify changes in the source data.\nConsider the following table as the last observed values of the declarations.\nid amount beneficiary date modified_date deleted_date 1 100 FEDERATION FRANCAISE DE CARDIOLOGIE 2025-12-01 2025-12-01 NaT 2 200 FEDERATION DES INFIRMIER 2025-12-02 2025-12-02 NaT 3 300 ORDRE DES VETERINAIRES 2025-12-03 2025-12-03 NaT 5 500 APHP 2025-12-01 2025-12-01 2025-12-03 Now consider that today\u0026rsquo;s file contains the following declarations.\nid amount beneficiary declaration_date 1 100 FEDERATION FRANCAISE DE CARDIOLOGIE 2025-12-01 2 220 FEDERATION DES INFIRMIERS 2025-12-02 4 400 ORDRE DES DIETETICIENS 2025-12-04 This new file presents 4 different situations.\nDeclaration 1 appears in today\u0026rsquo;s file with exactly the same information as in the historical file. Since nothing has changed in this declaration, we don\u0026rsquo;t want to do anything about it in the historical file. Declaration 2 already existed in the historical file but today\u0026rsquo;s version has two changes: the amount increased from 200 to 220 and a typo was corrected on the beneficiary (added an S at the end). We want to record this change and add this version of the declaration to history, with today\u0026rsquo;s modification date. Declaration 3 no longer appears in today\u0026rsquo;s file but existed in the history. We want to document in the historical file the disappearance date of this declaration. Declaration 4 is a new declaration that never appeared in the file before this version. We want to add it to the historical file. Declaration 5 is not in today\u0026rsquo;s file but the historical file mentions that the declaration had already disappeared in earlier versions of the file. We therefore expect no processing on this declaration. The simple case of additions and deletions # The appearance of new declarations and the disappearance of old ones are the simplest cases to handle. Since the files provide us with a unique id for declarations, we can simply compare the list of IDs from the historical file with today\u0026rsquo;s file. This procedure is very simple to implement in SQL and very fast.\nFor example, you can prepare the new declarations to inject into the file with this simple SQL query.\nselect declarations.*, current_date() as modified_date, cast(null as date) as deleted_date from declarations left join historical_declarations hist using (id) where hist.id is null This gives us declaration 4 to inject.\nid amount beneficiary date modified_date deleted_date 4 400 ORDRE DES DIETETICIENS 2025-12-04 2025-12-08 NaT And finally, we can identify the disappearance of declaration 3 with the following query.\nselect hist.id from historical_declarations hist left join declarations using (id) where hist.deleted_date is null and declarations.id is null Heavy modification detection # Managing modified declarations is much more complex. The declarations file actually contains around fifty columns that companies can modify at will. To identify declarations modified since the last version of the file, we need to create a SQL condition that contains the comparison of all fifty columns one by one to find all declarations that were already present in yesterday\u0026rsquo;s file but at least one value has been changed. Continuing the example started earlier, the query takes the following form.\nwith modified as ( select dec.* from declarations dec join historical_declarations h using (id) where h.deleted_date is null and not ( coalesce(h.amount, -1) = coalesce(dec.amount, -1) and coalesce(h.beneficiary, \u0026#39;__NULL__\u0026#39;) = coalesce(dec.beneficiary, \u0026#39;__NULL__\u0026#39;) and coalesce(h.date, \u0026#39;1900-01-01\u0026#39;) = coalesce(dec.date, \u0026#39;1900-01-01\u0026#39;) ) ) select *, current_date() as modified_date, cast(null as date) as deleted_date from modified This gives the following table to inject into our historical file.\nid amount beneficiary date modified_date deleted_date 2 220 FEDERATION DES INFIRMIERS 2025-12-02 2025-12-08 NaT This strategy has two limitations.\nThe query itself can quickly become unreadable with 50 conditions (instead of 3) to take into account. In truth, modern tools can work around this limitation with templating. At EurosForDocs, it\u0026rsquo;s Python code that organizes successive SQL calls. We can then create the query dynamically thanks to a simple for loop over the declaration variables.\nThe second problem with our strategy is performance. To verify that two versions of a declaration are identical, you must calculate 50 conditions. Some of these conditions can be particularly intensive, such as comparing two long strings. These limitations at the scale of several millions of rows and 50 columns can quickly become the main source of slowdown in a data pipeline.\nHash functions # Another more performant solution is based on the concept of a hash function. A hash function transforms arbitrary text into a signature (numeric or alphanumeric). This signature is characteristic of the initial text in the sense that applying the hash function multiple times to the same text will always produce the same signature. On the other hand, two texts that differ, even by a single typo, will obtain radically different signatures.\nLet\u0026rsquo;s take a simple case: French social security numbers. Most numbers are a combination of digits related to our birth date and place. The last two digits are, however, much less well known: they are precisely used in the context of a basic hash function.\nThe Luhn algorithm is a way to combine the digits of a number to obtain an integer as a signature. The image below shows how to calculate this signature for an arbitrary combination of digits.\nIn general, the Luhn algorithm is not limited to calculating this signature. In the case of the social security number, the last two digits are added and chosen specifically to force the signature to be a multiple of 10. Thus, if we encounter a number with a signature that is not a multiple of 10, we can be sure that this number contains at least one error. It is possible to use this property to verify that the digit provided in a form is not invalid without having to ask the health insurance for a list of all valid numbers.\nHash function limitations # One obvious limitation of hash functions is that there are far fewer unique signatures than possible texts. In the case of social security numbers, only 10 signatures are possible, only one (0) of which really makes sense. Most computer systems today encode integers on 64 bits: which represents 2**64=18 446 744 073 709 551 616 unique signatures. Even though this number is enormous, it is insignificant compared to the set of all texts (and their sub-parts) that can exist. Many texts will therefore share the same signature.\nThe result of a hash function can seem random and two very similar texts can obtain radically different numbers. This means that the probability that two different texts share the same signature is lower the greater the number of available signatures. Thus, one can always choose a hash function with enough available signatures to consider the probability that two different texts in our dataset share the same signature as zero.\nDetecting modifications through hashing # EurosForDocs uses a hash function to identify declarations modified between two versions of our source file. For each past or present declaration, the 50 columns of the file are concatenated to create a large text. This text can then be run through a hash function to obtain a signature of this version of the declaration. Identifying modifications is then very fast and very simple to implement: we check for each declaration whether the current signature value matches yesterday\u0026rsquo;s.\nid amount beneficiary date modified_date deleted_date declaration_hash pre_hash_content 1 100 FEDERATION FRANCAISE DE CARDIOLOGIE 2025-12-01 2025-12-01 NaT 5282952966449529016 FEDERATION FRANCAISE DE CARDIOLOGIE1002025-12-01 2 200 FEDERATION DES INFIRMIER 2025-12-02 2025-12-02 NaT 2026300923310215632 FEDERATION DES INFIRMIER2002025-12-02 3 300 ORDRE DES VETERINAIRES 2025-12-03 2025-12-03 NaT 13336717800038872971 ORDRE DES VETERINAIRES3002025-12-03 5 500 APHP 2025-12-01 2025-12-01 2025-12-03 17315167167027391093 APHP5002025-12-01 We can then directly calculate this hash on the new declarations and compare it with the historical hash to identify modified declarations.\nWITH declas_with_hash AS ( SELECT *, HASH( CONCAT( COALESCE(beneficiary, \u0026#39;__NULL__\u0026#39;), COALESCE(amount::VARCHAR, \u0026#39;__NULL__\u0026#39;), COALESCE(date::VARCHAR, \u0026#39;__NULL__\u0026#39;) ) ) AS declaration_hash FROM declarations ) SELECT old.id, old.declaration_hash::VARCHAR AS declaration_hash, declas_with_hash.declaration_hash::VARCHAR AS updated_declaration_hash FROM historical_declarations INNER JOIN declas_with_hash ON historical_declarations.id = declas_with_hash.id id declaration_hash updated_declaration_hash 1 5282952966449529016 5282952966449529016 2 2026300923310215632 1955208196671589357 This method provides performance gains. Each day, we only need to compare two integers for each declaration instead of fifty columns: this consumes much less memory (no need to read character strings) and is much faster.\nConclusion # Hash functions offer an efficient alternative for detecting modifications in large, frequently updated datasets. By transforming complex sets of columns into simple numeric signatures, they make it possible to significantly simplify SQL queries and improve the performance of data pipelines.\nIn the case of EurosForDocs, this approach made it possible to reduce the complexity of detecting modifications from dozens of SQL conditions to a simple integer comparison. The gains in terms of execution time and memory consumption are particularly notable when processing millions of rows daily and having to work with machines with limited memory.\nThis technique applies to many other data engineering use cases: file version tracking, duplicate detection, data integrity validation, or deduplication. It is important to choose a hash function suited to the size of your dataset to minimize the risk of collisions, even though these remain negligible in most practical contexts.\n","date":"16 December 2025","externalUrl":null,"permalink":"/en/articles/unicity_sha/","section":"Articles","summary":"As a data engineer, we are not always masters of our data sources. Particularly when using open data, we are at the mercy of the changes made by data producers.\n","title":"Using hash functions to simplify the creation of historical records","type":"articles"},{"content":" Introduction # L\u0026rsquo;association Data For Good développe depuis 2015 des outils numériques pour des associations et ONG. Chaque année, des dizaines de projets voient le jour grâce à la collaboration entre des bénévoles experts de la tech et des organisations à impact social ou environnemental.\nCes projets couvrent des domaines variés : surveillance de la pêche industrielle, détection de désinformation climatique, transparence dans la santé, ou encore lutte contre les inégalités. L\u0026rsquo;association rassemble une communauté de 6000 bénévoles experts en data et IA.\nCependant, les profils juniors en data science rencontrent des difficultés pour participer efficacement à ces projets. Bien qu\u0026rsquo;ils possèdent souvent des compétences techniques de base (SQL, Python), il leur manque souvent des compétences de base en développement logiciel pour contribuer de manière autonome dans un environnement professionnel.\nCet article est à destination des juniors qui pourraient se sentir concernés par cet angle mort dans leurs compétences. Il présente le programme Warmup Junior, un parcours d\u0026rsquo;apprentissage conçu spécifiquement pour les profils juniors afin d\u0026rsquo;acquérir ces compétences collaboratives en contribuant à un projet open source professionnel.\nQu\u0026rsquo;est-ce que le programme Warmup Junior ? # Le constat # Les profils juniors constituent une majorité des participants aux saisons Data For Good, qu\u0026rsquo;ils viennent d\u0026rsquo;une formation initiale ou d\u0026rsquo;une reconversion professionnelle. Pourtant, la plupart des formations en data science se concentrent sur les compétences analytiques (SQL, Python, statistiques) et négligent les compétences de base en développement nécessaires pour travailler dans un projet collaboratif.\nEn pratique, lorsqu\u0026rsquo;un junior rejoint un projet open source, il rencontre rapidement trois difficultés principales :\nL\u0026rsquo;utilisation de Git et GitHub : créer une branche, gérer les commits, comprendre l\u0026rsquo;historique du projet sont des opérations nouvelles pour beaucoup. Le processus de code review : soumettre son code pour validation, comprendre les commentaires et intégrer les retours demande une familiarité avec ces pratiques. La qualité du code : écrire du code qui fonctionne n\u0026rsquo;est pas suffisant; il faut aussi qu\u0026rsquo;il soit lisible, bien structuré et facile à maintenir pour les futurs contributeurs. Dans le contexte des saisons Data For Good, ces difficultés sont encore plus marquées. Un projet compte en moyenne seulement deux seniors data bénévoles, qui doivent à la fois développer et accompagner les juniors. Or, les projets de saison sont intenses, avec des deadlines serrées, et le contexte de bénévolat entraîne souvent une rotation importante des contributeurs. Dans ces conditions, il devient difficile pour un senior de prendre le temps d\u0026rsquo;expliquer les bases à un junior qui découvre ces outils pour la première fois.\nLa solution proposée # Le programme Warmup Junior propose d\u0026rsquo;accompagner les bénévoles juniors pour les rendre opérationnels sur un projet collaboratif. À noter : ce programme n\u0026rsquo;est pas une formation en data science. C\u0026rsquo;est un accompagnement aux bonnes pratiques de l\u0026rsquo;ingénierie logicielle. Son objectif est concret : corriger un bug simple et faire en sorte que cette correction soit intégrée dans le projet.\nLe programme s\u0026rsquo;appuie sur un projet mature qui fonctionne hors saison. Un projet mature signifie que les standards de développement sont déjà en place : tests unitaires, code review, conventions de nommage, documentation. En travaillant sur ce type de projet, vous découvrez directement ces pratiques professionnelles et vous apprenez à y contribuer selon ces règles.\nLes projets hors saison présentent plusieurs avantages pour l\u0026rsquo;apprentissage. Ils ne sont pas soumis aux deadlines serrées des saisons, ce qui signifie qu\u0026rsquo;une contribution peut prendre plusieurs semaines ou plusieurs mois sans poser de problème. Vous avez donc le temps de comprendre chaque concept à votre rythme, de tester, d\u0026rsquo;échouer et de réessayer. Les seniors qui maintiennent ces projets ont également plus de disponibilité pour répondre à vos questions et vous guider dans les bonnes pratiques.\nLe programme fonctionne principalement en autonomie : vous disposez d\u0026rsquo;un parcours d\u0026rsquo;étapes à suivre, avec des ressources sélectionnées pour comprendre chaque notion. Un mentor bénévole est disponible en asynchrone via la messagerie Data For Good pour répondre à vos questions et vous aider à débloquer une situation si nécessaire.\nLa suite de cet article détaille les étapes du programme dans le cadre d\u0026rsquo;une contribution aux projets hors saison Euros For Docs.\nParticiper au programme # Le projet EurosForDocs # Avant de commencer à contribuer, il est important de comprendre le contexte et les objectifs du projet. Cette compréhension vous permet de vous faire une idée de l\u0026rsquo;organisation générale du projet, et cette organisation se reflète généralement dans la structure du code. Par exemple, si un projet gère différents types de données (professionnels de santé, laboratoires, rémunérations), vous trouverez probablement ces concepts séparés dans le code.\nEuros For Docs est un projet qui existe depuis 2018 et qui a subi une refonte complète en 2023. Cette longue histoire et cette récente modernisation en font un projet mature et stable. Tous les standards de développement professionnel sont déjà en place : architecture structurée, tests unitaires, processus de review, outils d\u0026rsquo;automatisation. C\u0026rsquo;est précisément cette maturité qui en fait un terrain d\u0026rsquo;apprentissage idéal : vous découvrirez directement les pratiques utilisées dans les projets professionnels.\nLe projet vise à améliorer la transparence dans le domaine de la santé. Depuis 2014, les laboratoires pharmaceutiques ont l\u0026rsquo;obligation de déclarer toute rémunération versée aux professionnels de santé (médecins, pharmaciens, etc.). Ces déclarations sont publiques et disponibles sur une base de données open data. Cependant, cette base de données est difficile à exploiter : les données sont brutes, mal structurées et il n\u0026rsquo;existe pas d\u0026rsquo;interface utilisateur pour les consulter facilement.\nLe projet développe une pipeline de données qui s\u0026rsquo;exécute quotidiennement et qui réalise trois actions principales :\nTéléchargement : récupère automatiquement les données brutes depuis le site officiel. Nettoyage et structuration : traite ces données pour améliorer leur qualité et les rendre exploitables. Publication : met à jour le site web avec une interface publique permettant de rechercher et d\u0026rsquo;analyser les rémunérations. Pour approfondir la compréhension du projet avant de contribuer, plusieurs ressources sont disponibles :\nVision d\u0026rsquo;ensemble de la pipeline de données : présentation générale du fonctionnement du projet L\u0026rsquo;étude de cas ACTIV : exemple concret montrant la difficulté d\u0026rsquo;identifier correctement les bénéficiaires de rémunérations Méthode de déduplication des bénéficiaires : explication technique d\u0026rsquo;un des problèmes data principaux du projet Installation et exécution du projet # Téléchargement du projet # Le code source du projet Euros For Docs est public et accessible sur GitLab. Si vous n\u0026rsquo;êtes pas familier avec l\u0026rsquo;utilisation de GitLab (ou GitHub), il est conseillé de suivre ce MOOC de 2h créé par le pôle formation de Data For Good. Tous les concepts abordés dans ce mooc seront utiles dans la suite du programme.\nAvant de pouvoir contribuer, vous devez télécharger le projet sur votre machine et l\u0026rsquo;installer. Depuis la page du projet, vous pouvez obtenir l\u0026rsquo;URL pour télécharger le projet sur votre machine. Dans un terminal, placez vous dans le dossier dans lequel vous voulez télécharger le projet et lancez la commande suivante.\ngit clone git@gitlab.com:eurosfordocs/ts-v2.git Celle-ci va télécharger l\u0026rsquo;intégralité du projet sur votre machine. À partir de maintenant, vous pouvez modifier à volonté le code sur la machine sans que cela n\u0026rsquo;impacte le projet pour les autres contributeurs. Les prochaines étapes expliqueront comment partager vos modifications.\nUne manière alternative de télécharger le projet est d\u0026rsquo;ouvrir directement votre éditeur de code. Tous les éditeurs modernes ont une interface pour ouvrir un projet à partir d\u0026rsquo;une URL. Par exemple, la page d\u0026rsquo;accueil de VSCode propose justement l\u0026rsquo;option de cloner un dépôt Git.\nCréation d\u0026rsquo;une clé SSH # Les plateformes collaboratives telles que GitLab ont la notion de droits attribués aux utilisateurs. Il est donc essentiel que les utilisateurs soient authentifiés avant toute modification. Une des méthodes les plus pratiques et sûres pour s\u0026rsquo;authentifier sans avoir à taper un mot de passe à chaque interaction avec le site web est l\u0026rsquo;utilisation de clés SSH. Ces clés sont un moyen de dire à GitLab que cet ordinateur appartient à un compte utilisateur particulier et donc d\u0026rsquo;être automatiquement authentifié.\nPour mettre en place ce système, vous devez créer une clé sur votre ordinateur et la renseigner dans vos paramètres utilisateurs sur GitLab. La documentation de GitLab vous propose un tutoriel pour créer et configurer vos clés : https://docs.gitlab.com/user/ssh/. Cette étape peut prendre un peu de temps la première fois le temps de comprendre les concepts.\nCette étape n\u0026rsquo;a pas besoin d\u0026rsquo;être répétée pour contribuer sur d\u0026rsquo;autres projet sur GitLab. Par contre il faudra reconfigurer de nouvelles clés si vous changez d\u0026rsquo;ordinateur ou si vous contribuez à un projet hébergé sur une autre plateforme (GitHub par exemple).\nInstallation de l\u0026rsquo;environnement # Pour faire fonctionner le projet sur sa machine, il faut installer toutes les dépendances du projet. Tous les projets matures contiennent un fichier nommé README.md à la base du projet. Ce fichier contenant du texte formaté est en particulier affiché en bas de la page d\u0026rsquo;accueil du projet sur GitLab. C\u0026rsquo;est dans celui-ci que vous trouverez les instructions d\u0026rsquo;installation spécifiques à ce projet.\nLe projet EurosForDocs est un projet assez simple en termes de technologie, l\u0026rsquo;essentiel est fait en python. De plus toutes les étapes d\u0026rsquo;installation sont regroupées dans une seule commande make install. Cette commande va en déclencher deux autres :\nla création d\u0026rsquo;un environnement virtuel python, l\u0026rsquo;installation des librairies nécessaires (documentées dans requirements.txt) dans cet environnement. Un environnement virtuel est un moyen d\u0026rsquo;isoler l\u0026rsquo;installation des librairies d\u0026rsquo;un projet spécifique. Ainsi, si vous travaillez sur deux projets qui ont besoin d\u0026rsquo;une même librairie dans deux versions distinctes, chaque projet aura sa propre version indépendamment de comment évolue l\u0026rsquo;autre. Même si les détails de cette partie sont cachés sur EurosForDocs, il est recommandé aux personnes non familières avec cette notion de se former à ce concept. Cette vidéo de 10min est un bon point de départ pour aborder cette notion.\nConfigurer les variables d\u0026rsquo;environnement # Tous les projets informatiques nécessitent l\u0026rsquo;utilisation d\u0026rsquo;informations que l\u0026rsquo;on ne souhaite pas divulguer au grand public. Par exemple, si le projet nécessite de se connecter à une base de données, on n\u0026rsquo;a pas envie de mettre directement dans le code l\u0026rsquo;adresse et le mot de passe d\u0026rsquo;accès à la base. À la place, on va intégrer dans le code des variables spécifiques : les variables d\u0026rsquo;environnement. Ainsi, lorsque le code aura besoin de la valeur de ces variables, il va demander à la machine qui l\u0026rsquo;héberge la valeur à utiliser.\nCela implique par contre que chaque machine qui souhaite utiliser le code ait accès à cette information. Pour cela, la convention est d\u0026rsquo;avoir un fichier texte dans le projet qui va contenir la liste de ces variables d\u0026rsquo;environnement ainsi que leur valeur à utiliser. Cette méthode permet aussi d\u0026rsquo;avoir des comportements différents du code : par exemple, en changeant les valeurs des variables d\u0026rsquo;environnement on peut aller requêter une base de test que l\u0026rsquo;on peut se permettre de casser au lieu de requêter la base de production beaucoup plus sensible. Cette vidéo de 5min aborde les étapes essentielles pour comprendre ce concept.\nPar exemple, le projet EurosForDocs conseille de vérifier le fonctionnement de la pipeline avec une version allégée grâce à ces paramètres.\n# .env ENVIRONMENT=\u0026#34;CI\u0026#34; DUCKDB_MEMORY_LIMIT=8G Exécution du projet # Une fois l\u0026rsquo;ensemble des librairies installées et l\u0026rsquo;environnement configuré, on peut exécuter le projet pour vérifier que tout fonctionne correctement. Les instructions spécifiques pour lancer un projet sont documentées dans le README.md et peuvent être très différentes selon le type de projet (site web, pipeline, \u0026hellip;) et les choix de technologie et d\u0026rsquo;infrastructure.\nDans le cas particulier d\u0026rsquo;EurosForDocs, nous ne nous intéressons qu\u0026rsquo;à faire tourner la pipeline de traitement des données et en particulier la pipeline allégée de test. Encore une fois dans ce projet, une seule commande (make process) lance l\u0026rsquo;intégralité du traitement.\nRésolution d\u0026rsquo;un ticket # Obtenir un ticket # Une fois l\u0026rsquo;installation réussie et la pipeline fonctionnelle, contactez le chef de projet pour obtenir un ticket d\u0026rsquo;amélioration. Un ticket décrit une tâche à réaliser : il peut s\u0026rsquo;agir de corriger un bug, d\u0026rsquo;optimiser une partie du code, ou d\u0026rsquo;ajouter une petite fonctionnalité. Ce ticket vous donne un objectif concret et vous guide vers une partie spécifique du code à comprendre et à modifier.\nComprendre l\u0026rsquo;architecture # Prenez le temps d\u0026rsquo;explorer la structure du code. Regardez comment les différents modules sont organisés, quels fichiers contiennent quelles fonctions, comment les données circulent entre les différentes étapes. Cette exploration vous aidera plus tard à localiser rapidement la partie du code concernée par votre contribution.\nCréation d\u0026rsquo;une Pull Request # Dans un projet collaboratif, on ne modifie jamais directement le code principal du projet. Chaque contributeur travaille sur sa propre copie du code (appelée une \u0026ldquo;branche\u0026rdquo;) pour résoudre son ticket. Une fois la solution implémentée et testée localement, cette copie est proposée pour intégration dans le projet principal via une Pull Request (ou \u0026ldquo;Merge Request\u0026rdquo; sur GitLab).\nQu\u0026rsquo;est-ce qu\u0026rsquo;une Pull Request ?\nUne Pull Request est une demande de fusion de votre code dans le projet principal. Elle permet de soumettre votre travail à une review (relecture) par d\u0026rsquo;autres contributeurs, généralement des seniors du projet.\nPourquoi passer par une review ?\nLa review a plusieurs objectifs :\nVérifier que votre code résout correctement le problème posé par le ticket S\u0026rsquo;assurer que le code s\u0026rsquo;intègre bien avec le reste du projet (logique cohérente, pas de régression) Améliorer la qualité du code en suggérant des améliorations (lisibilité, performance, meilleures pratiques) C\u0026rsquo;est un processus d\u0026rsquo;apprentissage : les commentaires des reviewers vous aident à progresser et à comprendre les standards du projet. Cet article présente l\u0026rsquo;intérêt de la review dans un projet collaboratif.\nComment créer une Pull Request ?\nLe pôle formation de Data for Good propose un MOOC rapide qui explique pas à pas comment préparer et proposer une pull request : lien vers le MOOC\nTests unitaires # Lorsque vous écrivez du code, vous vérifiez évidemment qu\u0026rsquo;il résout le problème posé. Vous pouvez même tester différents cas particuliers pour vous assurer de sa robustesse. Cependant, quand vous quittez le projet, la personne qui reprendra votre code ne saura pas forcément quel était le rôle exact de ce code ni tous les cas particuliers qu\u0026rsquo;il est censé traiter.\nPourquoi écrire des tests ?\nLes tests unitaires sont des petits programmes qui vérifient automatiquement que vos fonctions se comportent comme prévu. Ils exécutent vos fonctions avec des arguments connus et vérifient que les résultats obtenus correspondent aux résultats attendus.\nL\u0026rsquo;intérêt principal : si quelqu\u0026rsquo;un modifie votre code plus tard (par exemple pour corriger un bug ou ajouter une fonctionnalité), les tests vont détecter automatiquement si ce changement casse quelque chose de manière inattendue. C\u0026rsquo;est une sécurité qui protège le projet contre les régressions.\nCette vidéo introduit le concept de tests unitaires pour la data science.\nTests dans le projet Euros For Docs\nLes projets matures comme Euros For Docs contiennent déjà de nombreux tests unitaires. Vous pouvez voir un exemple concret dans le fichier test_clean_functions.py qui teste les fonctions de nettoyage des données.\nIntégrer les tests dans votre contribution\nQuand vous contribuez au projet, vous devez prendre en compte les tests existants :\nPour corriger un bug : mettez à jour les tests pour vérifier que le bug est bien résolu Pour ajouter une fonctionnalité : ajoutez de nouveaux tests qui vérifient le comportement de votre nouvelle fonctionnalité Pour optimiser du code : assurez-vous que tous les tests passent toujours, garantissant que votre optimisation n\u0026rsquo;a pas cassé le comportement existant Qualité du code # Résoudre un problème technique n\u0026rsquo;est qu\u0026rsquo;une partie du travail. Votre code doit également être facile à comprendre et à modifier pour les futurs contributeurs qui devront le maintenir ou l\u0026rsquo;améliorer.\nPourquoi la qualité du code est importante ?\nLe code que vous écrivez aujourd\u0026rsquo;hui sera lu, modifié et débogué par d\u0026rsquo;autres personnes (ou par vous-même dans quelques mois). Un code de qualité réduit le temps nécessaire pour comprendre ce qu\u0026rsquo;il fait et limite les risques d\u0026rsquo;introduire des bugs lors de modifications futures.\nLes principes de base\nDeux aspects principaux déterminent la qualité d\u0026rsquo;un code :\nLa lisibilité : des noms de variables et de fonctions clairs et explicites permettent de comprendre rapidement le rôle de chaque élément sans avoir à déchiffrer la logique ligne par ligne La structure : une organisation cohérente du code facilite la navigation entre les différents modules et permet de localiser rapidement la partie concernée par une modification Apprendre les bonnes pratiques\nCes concepts peuvent sembler abstraits au début. Sachez qu\u0026rsquo;une part importante de la code review consiste justement à proposer des suggestions pour améliorer la qualité de votre code. C\u0026rsquo;est un processus d\u0026rsquo;apprentissage : chaque review vous fait progresser.\nCette vidéo propose une première introduction aux bonnes pratiques de développement. Il est important de comprendre que ces pratiques ne sont pas des règles absolues mais plutôt un état d\u0026rsquo;esprit à adopter progressivement. Personne ne s\u0026rsquo;attend à ce qu\u0026rsquo;un junior produise du code de qualité professionnelle dès le premier essai. L\u0026rsquo;objectif est plutôt de prendre conscience de ces concepts et de chercher à les appliquer régulièrement. Avec l\u0026rsquo;expérience et les retours des reviews, vous progresserez naturellement.\nPre-commit hooks # Les pre-commit hooks sont des vérifications automatiques qui s\u0026rsquo;exécutent avant que vous n\u0026rsquo;enregistriez votre code (commit) dans Git. Leur rôle est de s\u0026rsquo;assurer que votre code respecte les conventions de style et de qualité définies par le projet.\nPourquoi utiliser des pre-commit hooks ?\nSans ces outils, chaque contributeur pourrait avoir son propre style de code : des espaces différents, des longueurs de lignes variables, des imports non triés, etc. Résultat : le code devient difficile à lire et à maintenir, même si techniquement il fonctionne. Les pre-commit hooks garantissent une cohérence automatique du style sur l\u0026rsquo;ensemble du projet.\nComment ça fonctionne ?\nLorsque vous tentez de faire un commit, les hooks vérifient automatiquement votre code. S\u0026rsquo;ils détectent des problèmes de style, le commit est bloqué et vous recevez des instructions pour corriger les erreurs. Une fois les corrections apportées, vous pouvez refaire votre commit qui sera accepté.\nLes outils utilisés : Ruff\nLe projet Euros For Docs utilise notamment Ruff, un outil Python moderne qui vérifie et corrige automatiquement le style du code. Ruff est rapide et combine les fonctionnalités de plusieurs outils classiques (linters, formatters) en un seul outil.\nConfigurer son IDE pour auto-formater\nPour éviter d\u0026rsquo;avoir à corriger manuellement à chaque commit, vous pouvez configurer votre IDE (VS Code, PyCharm, etc.) pour qu\u0026rsquo;il formate automatiquement votre code selon les mêmes règles que Ruff.\nDans VS Code : installez l\u0026rsquo;extension \u0026ldquo;Ruff\u0026rdquo; qui formate automatiquement votre code à la sauvegarde Dans PyCharm : configurez Ruff comme formateur externe dans les paramètres Ainsi, votre code sera déjà formaté correctement avant même de faire votre commit, et les pre-commit hooks passeront sans problème. C\u0026rsquo;est plus efficace et vous évite des allers-retours frustrants.\nIntégration continue (CI) # L\u0026rsquo;intégration continue (CI) est un système automatique qui vérifie votre code à chaque fois que vous poussez (push) vos modifications sur GitLab. Même si les pre-commit hooks ont vérifié votre code localement, la CI effectue une double vérification sur un environnement propre, identique pour tous les contributeurs.\nQue vérifie la CI ?\nLa CI exécute automatiquement plusieurs vérifications sur votre Pull Request :\nLes tests unitaires : tous les tests du projet sont exécutés pour s\u0026rsquo;assurer que votre contribution n\u0026rsquo;a pas cassé le comportement existant Le style du code : les mêmes vérifications que les pre-commit hooks sont relancées (formatage, conventions, etc.) D\u0026rsquo;autres vérifications spécifiques au projet : selon les projets, la CI peut aussi vérifier la documentation, la couverture de tests, ou d\u0026rsquo;autres critères de qualité Pourquoi c\u0026rsquo;est important ?\nLa CI garantit que tous les contributeurs travaillent selon les mêmes standards, même s\u0026rsquo;ils ont des configurations locales différentes. C\u0026rsquo;est une sécurité supplémentaire qui protège la qualité du projet principal.\nComprendre les résultats de la CI\nAprès avoir créé votre Pull Request, la CI se déclenche automatiquement. Sur la page GitLab de votre PR, vous verrez le statut de la CI :\nSi tous les checks sont verts ✅ : votre code respecte les standards et peut être fusionné Si un check est rouge ❌ : la CI a détecté un problème (test qui échoue, problème de style, etc.) En cas d\u0026rsquo;échec, l\u0026rsquo;interface GitLab vous indique précisément quel test a échoué ou quelle vérification de style a été détectée, vous permettant de corriger le problème avant de demander une nouvelle review.\nConclusion # Le programme Warmup Junior propose un parcours pratique pour les data analysts débutants qui souhaitent contribuer aux projets Data For Good. En s\u0026rsquo;appuyant sur un projet stable hors saison comme Euros For Docs, il permet d\u0026rsquo;acquérir progressivement les compétences collaboratives nécessaires pour travailler efficacement dans un environnement professionnel.\nCe que vous aurez appris\nÀ l\u0026rsquo;issue du programme, vous maîtriserez les bases du développement collaboratif :\nLa gestion de projet avec Git et les Pull Requests L\u0026rsquo;écriture et la maintenance de tests unitaires Les standards de qualité de code et leur importance Les outils d\u0026rsquo;automatisation (pre-commit hooks, CI) qui garantissent la cohérence du projet Ces compétences vous permettront de contribuer de manière plus autonome aux projets de saison Data For Good, où vous pourrez vous concentrer sur les aspects data plutôt que sur la prise en main des outils.\nSe lancer dans le programme\nPour participer au programme Warmup Junior :\nSe connecter au Slack Data For Good et se présenter sur le canal #6_eurosfordocs. Installer l\u0026rsquo;environnement du projet en suivant le README. Faire valider votre installation et obtenir un premier ticket. Suivre les étapes décrites dans cet article : correction du bug, tests, Pull Request, intégration des retours. Le programme se déroule à votre rythme, avec l\u0026rsquo;accompagnement d\u0026rsquo;un mentor disponible en asynchrone pour répondre à vos questions.\nAu-delà du programme\nUne fois votre première contribution réussie, vous pouvez continuer à contribuer au projet hors saison ou passer aux projets de saison. Les compétences acquises sont transférables à d\u0026rsquo;autres projets open source, professionnels ou personnels.\nLe programme Warmup Junior constitue ainsi un premier pas concret vers une contribution autonome et efficace dans l\u0026rsquo;écosystème Data For Good.\n","date":"November 1, 2025","externalUrl":null,"permalink":"/projets/junior_warmup/","section":"Projets","summary":"Introduction # L’association Data For Good développe depuis 2015 des outils numériques pour des associations et ONG. Chaque année, des dizaines de projets voient le jour grâce à la collaboration entre des bénévoles experts de la tech et des organisations à impact social ou environnemental.\n","title":"Contribuer à un projet data : le programme Warmup Junior","type":"projets"},{"content":" The challenge of identifying beneficiaries # The healthcare ecosystem brings together several types of actors: pharmaceutical laboratories, healthcare professionals and patient associations. These actors maintain financial and influence relationships with each other that can create conflicts of interest.\nTo limit these risks, the Transparence Santé database requires healthcare companies to publicly declare the benefits and remuneration they provide to healthcare professionals and other sector actors. This database is used by the EurosForDocs project to analyze these financial flows.\nBut to precisely analyze these interest ties, you must be able to unambiguously identify each beneficiary of benefits or remuneration. However, the government platform gives companies great freedom in drafting their declarations. This flexibility leads to a practical problem: the same beneficiary can be described in many different ways depending on the companies. It can then be complicated to group all declarations concerning them.\nThe ideal situation for grouping the different declarations relating to the same beneficiary would be the presence of a unique national identifier. Healthcare professionals have exactly such a number: the RPPS number. An older reference system (the ADELI number) is also available and can be converted to RPPS for most professions. Scientific societies and patient associations can be identified by their national association number (RNA) or SIREN number.\nIn practice, declarations are far from meeting expected quality standards. The filing rate of a SIREN or RNA number for legal entities is only 50%. The situation was similar for healthcare professionals, but a platform update made it possible to increase the filing rate to 90%.\nOne of EurosForDocs\u0026rsquo;s reprocessing objectives is to merge all beneficiary accounts relating to the same physical entity, even in the absence of a national identifier. To do this, we have implemented a four-step system:\nCorrect incoherent identifiers. We correct declarations that have RPPS numbers but for which the names, first names and profession declared are incoherent compared to information in the official RPPS directory. This step is the subject of a dedicated article.\nAssign identifiers. We attempt to find the missing identifier of a beneficiary by searching for it in an official directory (RPPS for healthcare professionals, SIREN/RNA for legal entities).\nSearch for direct links. When identification in a directory fails, we search for direct matches between accounts by comparing their information (name, first name, profession, etc.).\nCreate entities. An algorithm automatically groups all accounts that are linked to each other, directly or through other accounts to recreate the physical entities to which they correspond.\nAccount matching methods # As mentioned in the previous section, the ideal situation consists of having a national identifier for each beneficiary account. When none is present, we seek to find one through different sources of truth.\nIdentifier re-assignment # Healthcare professionals are the simplest cases to handle. The health directory (or RPPS) lists all healthcare professionals practicing in France, sometimes with different variants for their name, first name or postal code. It also includes for each professional their RPPS and/or ADELI number. We can thus attempt to directly assign an RPPS number to healthcare professionals declared without any identifier.\nFor each of these professionals, we search the directory for a person with the same name, first name and profession. If there is only one RPPS number in the directory with this information (thus no homonyms that could create ambiguity), we assign it to this account.\nSeveral variants of this logic are tested to adjust tolerance thresholds on the information considered and try to overcome homonym problems. For example, we can try to use the postal code if it is declared to resolve ambiguities, or work on subparts of a compound name. Unlike the techniques applied in this article, we do not assign an RPPS number to an account if we do not obtain an exact match for a given approach. We thus choose not to be able to handle simple typographical errors, which would open the door to too many false positives. Among the 2 million accounts of professionals declared without RPPS, 60% are assigned an identifier at the end of this procedure.\nIn theory, we should be able to apply the same logic to legal entities through association and SIREN directories. Unfortunately, the only information that is truly usable is the entity name. While you would expect to find the exact name for a natural person (sometimes with maiden name/married name issues), an association name allows for greater variations without questioning the intelligibility of the declaration. For example, in this case study, the Clinical and Therapeutic Association for Children of the Val de Marne was identified under different mentions, ranging from the full name to the acronym ACTIV through condensed versions such as \u0026ldquo;Ass Cliniq Therap Infantil\u0026rdquo;. Such diversity does not allow applying an assignment logic similar to that for natural persons.\nDuring data exploration, we also identified special cases. Some companies declare identification numbers that do not appear to correspond to national repositories, but seem to be uniquely linked to the same beneficiary. We deduced that these numbers must be internal identification numbers. We then use these numbers (by company) as national identifiers to link different accounts of the same entity together.\nFinally, some account duplicates resist all our methods (including ones not yet presented). These duplicates are generally identified by users during their exploration of certain specific people or associations. We then implemented a manual modification system that allows assigning identifiers to beneficiary accounts.\nDirect link between accounts # A second strategy for merging accounts consists of proving that two beneficiary accounts refer to the same entity, even in the absence of an identifier. In the ideal case, the first account has an identifier that will be propagated to the second. When no account has an identifier, this link nonetheless allows merging the two accounts, hoping that another direct link with a third account will allow subsequent identification.\nHealthcare professionals # The first strategy implemented applies to healthcare professionals. We seek to group beneficiary accounts that have the same name, first name, profession and postal code, but may be declared by different companies.\nHowever, this approach can produce false positives, even with the requirement of an entered postal code. Imagine for example a case where an account without RPPS coexists with two other accounts sharing the same name, first name, profession and postal code, but possessing distinct RPPS numbers. In this situation, assigning the correct RPPS becomes impossible. After completing RPPS as much as possible in the previous steps, we apply an additional constraint: each group of homonymous accounts can contain only one RPPS number. This limitation significantly reduces the risks of assignment error.\nLegal entities # Regarding legal entities, the strategy is similar but can only be based on the entity name. Here, the risk of merging homonymous accounts is much higher: it is not uncommon for different entities to have the same acronym and for companies to declare only this one. We also identified a substantial number of declarations where the beneficiary name is a non-indicative keyword: \u0026ldquo;Hospital\u0026rdquo; for example.\nThese different cases make it important to have a mechanism for limiting false positives. As for healthcare professionals, we require a group of homonymous beneficiaries to have no more than one identifier among them to allow accounts without identifiers to receive one. Furthermore, we prohibit links between accounts whose names are non-indicative words.\nManual links # Finally, certain specific studies conducted by our users have reported links between accounts for which no identifier is entered. Most of the time, we try to manually assign them identifiers as mentioned in the previous section.\nUnfortunately, it can be difficult to obtain an identifier for certain entities. For example, some inter-entity working groups do not technically have legal existence but receive funding for their activities. Even if these funds are surely attributed accountingly to legal entities that participate in these groups, the declaration mentions only the group, which will then have no identifier. In these particular cases, we then create a new database of links between accounts that allows linking accounts two by two.\nCreating entities # The previous section presented us with several cases of links between accounts. Depending on the quality of declarations, these links can be numerous and diverse. We thus need a strategy to reconstitute unique and quality entities from this set of declared accounts and the links between them.\nGrouping by identifier # Consider the simplest case where multiple accounts are linked through the same identifier. We can then group all accounts with the same identifier. For example, imagine that the following accounts are all linked to the same RPPS number:\nid name first_name profession rpps 1 Dupont Christine pharmacist 1000 2 Dupont Christine 1000 3 Dupont Cristine 1000 We seek to create an entity for this pharmacist that is the best possible combination of information contained in all accounts. Here, the name poses no problem as it is identical everywhere. The final name of our entity will therefore be Dupont.\nOur deduplication strategy allows us to enrich our data with the profession of this person. Indeed, the declarations corresponding to beneficiary accounts 2 and 3 have not documented a profession. Thanks to linking these 3 accounts through the RPPS number, we can assign a profession to all accounts, which will improve the quality of declarations without this information.\nThis system also allows us to unify certain variable information. For example, account number 3 has a typo in the first name: the h is missing. It could just as well provide a variant of the first name: we have cases of Marie-Christine simply declared as Marie or Christine. There is thus naturally variability in the declared data. We can choose the most relevant variant to create our final entity. Thus, all declarations with incorrect and/or variant information can be modified to harmonize all declarations linked to this person.\nTo link a beneficiary account to an entity, it is preferable to create an ID for this entity. It is important to have an identifier that has a certain stability. Indeed, we receive new declarations or modifications daily. We want an identifier that changes little when new declarations are created, so that users can easily find the beneficiaries they are interested in from one day to the next.\nThe solution we chose is to use the smallest ID present among duplicate accounts. The addition of new accounts to the list of duplicates will not change the reference ID for the group. Updating declarations or improving merge logic can change the ID, but the proportion of affected accounts will be relatively small.\nImpact of varied relationships # The logic of grouping by unique identifier becomes more complex when multiple types of links coexist between accounts.\nConsider the following example: accounts 0 and 1 share the same RPPS number, account 2 is linked to account 1 via a company\u0026rsquo;s internal identifier, and account 3 is directly linked to account 1 by a data match.\nIf we limit ourselves to RPPS grouping (red box), we would exclude accounts 2 and 3 from the final entity, while they correspond to the same beneficiary. The solution is to extend the grouping recursively: all accounts linked to a member of the initial group must be included in the final entity. This logic applies iteratively until no new accounts can be added.\nOnce all linked accounts have been identified, we apply the same deduplication strategy as before to determine the name, first name and other final characteristics of the entity.\nGrouping sub-components # This iterative logic of needing to search for new accounts linked to a group member through different types of links is fairly complex to implement when placing ourselves in the context of data in the form of an Excel table; which we implicitly did in this article and previous ones about EurosForDocs. However, a paradigm shift will allow us to implement this logic extremely simply. This paradigm is data representation in network form.\nA network consists of a list of entities (nodes) that can be linked together through different mechanisms. The concept of networks is fairly well-known today through social networks, where people are connected by \u0026ldquo;friendship\u0026rdquo; links on Facebook or users connected to products and companies in an e-commerce database for example.\nTo create our network of duplicates, we must ask ourselves two main questions: what will the nodes of the network consist of and what will the links between them be. First, our network will contain all beneficiary accounts as nodes. However, we will also add as nodes all identifiers present in the database. We will thus have a set of nodes corresponding to different SIRENs, another set for RPPS numbers, etc\u0026hellip; The companies\u0026rsquo; internal identifiers that we mentioned earlier will also generate nodes.\nNext we will seek to link these nodes together. All the business rules detailed earlier will allow us to link nodes together. The presence of a declared (or found) RPPS number allows linking the node corresponding to this beneficiary with the node corresponding to their RPPS number. Direct relationships between accounts can also be represented by links between their respective nodes. This is the representation that was used in the previous example. Once this network is created, we get something that will resemble the following image, but with approximately 8 million nodes and 8 million links between these nodes.\nIf you look carefully at the network, you realize that nodes are naturally organized into 4 groups. In each of these groups, beneficiaries are linked to each other either directly or through a common link with an identification number. The group at the bottom left shows clearly that most nodes organize around a SIREN number and an RNA number, but with nodes on the left grouped around node 37, itself linked to the rest of the group via direct relationships with other beneficiary accounts. Each of these groups corresponds to all nodes linked to each other more or less closely; that is, to a final entity.\nNetworks as mathematical objects possess a vast range of algorithms that make it possible to explore them and deduce their properties. In particular, the connected components algorithm will explore a network and distribute nodes into groups so that it is always possible to reach one node in the group from another, possibly passing through other intermediate nodes, by following the links. Conversely, two nodes not belonging to the same group will not be accessible to each other.\nThis new formalism is then used to extract groups of beneficiary accounts that will make it possible to create entities. Since the connected components problem is relatively old, we have access to optimized implementations for graph-type data. This makes the procedure much more efficient than manual code; potentially in a formalism and technology not intended for this type of problem. Being able to call a well-known algorithm also reduces the amount of code (since we can call a dedicated tool) and facilitates documentation. Ultimately, we had 7.1 million beneficiary accounts that we were able to deduplicate into 2.1 million entities.\nManaging inconsistencies # The connected components algorithm reveals an important problem: some groups contain multiple identifiers of the same type (multiple RPPS or multiple SIREN). This situation indicates an error in the data, as each identifier should be unique for an entity.\nIn the example illustrated, the bottom group contains two distinct RPPS numbers (77 and 75), suggesting that two different entities have been incorrectly linked. Beneficiary account 2 likely presents an incorrect link. More complex situations exist, such as the group on the left where SIREN nodes are found on the periphery of the structure.\nEntity creation through connected components has two advantages. It allows efficient grouping of linked accounts while automatically identifying groups with inconsistencies. To limit processing errors, we choose not to merge accounts belonging to an inconsistent group, but to mark them for later processing, automatic or manual.\nConclusion # The deduplication of beneficiary accounts from the Transparence Santé database requires a progressive approach combining identifier assignment, direct matches and algorithmic grouping. Graph modeling transforms this complex problem into a standard connected components algorithm, making it possible to efficiently process 7.1 million accounts to obtain 2.1 million distinct entities.\nThis methodology provides a structured framework for entity resolution: start with reliable identifiers, expand with direct matches, then use graph theory to manage multiple relationships. Automatic detection of inconsistencies maintains data quality while identifying cases requiring manual intervention.\n","date":"14 October 2025","externalUrl":null,"permalink":"/en/articles/entity_resolution/","section":"Articles","summary":"The challenge of identifying beneficiaries # The healthcare ecosystem brings together several types of actors: pharmaceutical laboratories, healthcare professionals and patient associations. These actors maintain financial and influence relationships with each other that can create conflicts of interest.\n","title":"Data deduplication: using entity resolution on the Transparence Santé database","type":"articles"},{"content":" Data quality is a central issue in exploiting public databases. As part of the EurosForDocs project, which aims to bring transparency to financial ties between pharmaceutical companies and healthcare professionals, this issue is particularly critical. The reliability of analyses depends on our ability to unambiguously identify each healthcare professional receiving remuneration or benefits.\nThe RPPS (Shared Directory of Health Professionals) is a national government directory that lists all healthcare professionals in France and assigns them a unique and public number. This number is for example visible in the \u0026ldquo;Legal Information\u0026rdquo; section of a practitioner\u0026rsquo;s page on Doctolib, or on a prescription. In theory, the RPPS number should guarantee a reliable association between a remuneration declaration from a company and a healthcare professional. It is therefore essential to ensure that this information is as accurate as possible. However, in practice, data entry errors are frequent. It is not uncommon for the same professional to be assigned multiple RPPS numbers by the same company, creating conflicts that distort the analysis.\nThis article presents a methodology for detecting and correcting these inconsistencies on a large scale. We detail a fuzzy matching approach that consists of measuring the similarity between declared data and an official source. Depending on the level of similarity measured, you can then correct the data. This method makes it possible to automate identifier cleanup and significantly improve database quality.\nFor a more general view of EurosForDocs project data quality issues, you can consult this article.\nThe problem: unique identifiers that aren\u0026rsquo;t # The RPPS number is the cornerstone of the declaration system. Each healthcare professional should be associated with a unique number to guarantee reliable identification across different declarations from different companies.\nHowever, the reality of the data is more complex. We observe many cases where the same company declares multiple remuneration with the same name, first name, profession and postal code of beneficiary (which seems to indicate the same person) but with different RPPS numbers. This situation creates an ambiguity: is it a data entry error or two distinct but same-named professionals?\nTo resolve this doubt, the procedure consists of comparing the official information linked to each declared RPPS number with the other information declared by the company. This approach makes it possible to identify absurd RPPS numbers compared to the declared information, and to determine the number that seems most relevant compared to the declaration.\nLet\u0026rsquo;s take a concrete example:\nA laboratory declares a beneficiary, \u0026ldquo;Jean Crochet\u0026rdquo;, assigning him two RPPS numbers: 10002956406 and 10003257325.\nThe RPPS directory confirms that number ...406 indeed belongs to Dr. Jean Crochet, a doctor practicing in the stated department. The information is consistent. Conversely, number ...325 is assigned to Dr. Nathalie Bourgeois, another practitioner. The information is clearly inconsistent. This simple cross-check is sufficient to invalidate the second RPPS number and resolve the ambiguity. The challenge is not conceptual but operational: with more than 12,500 similar cases identified, and new cases potentially appearing daily, manual processing is unthinkable. It is therefore necessary to develop an automated method to apply this reasoning systematically and reliabilize the database.\nA flexible approach: textual similarity # Simple identifier verification quickly runs into another reality: declared information (name, first name) is often close but not strictly identical to that in the directory. A typo, an inversion between name and first name, or the use of a maiden name can be enough to incorrectly invalidate a match.\nFor example, a doctor \u0026ldquo;Jean-Luc Vilatte\u0026rdquo; is declared with two RPPS numbers. The official directory indicates that one number belongs to \u0026ldquo;Jean-Luc Vallet\u0026rdquo; and the other to \u0026ldquo;Jean-Luc Villate\u0026rdquo;. A strict comparison would reject both options. However, many algorithms offer different ways to measure the similarity between two character strings. The EurosForDocs project chose to work with the Jaro-Winkler metric. The exact definition of this metric not being the objective of this article, curious readers can refer to this article. Using this metric, we measure 97% similarity for \u0026ldquo;Villate\u0026rdquo; versus \u0026ldquo;Vilate\u0026rdquo; but only 74% versus \u0026ldquo;Vallet\u0026rdquo;. This metric therefore allows us to identify the name that corresponds least to the declaration.\nRather than seeking an exact match, our method will create a similarity score between the declared information and the official information. This score is defined as the sum of the similarity of first names and the similarity of surnames. An absurd RPPS number will have a similarity score close to zero while a perfect declaration will have a score of 2 (100% for each part of the identity). This approach, known as fuzzy matching, provides the flexibility needed to handle various types of data entry errors.\nManaging common entry errors # It should be noted that even in the RPPS directory, the same professional can appear under multiple names. A typical case is the presence of female doctors who appear with different combinations of their maiden name and married name. In this case, we calculate the similarity score for all variations. The best score for each RPPS number will help identify the most relevant number.\nBut there are also different types of data entry errors that give poor similarity scores and don\u0026rsquo;t allow us to correctly select the correct RPPS number.\nName/first name inversions: Sometimes the name and first name fields are inverted during entry. To neutralize this effect, we calculate similarity for both name/first name and first name/name (in addition to traditional name/name and first name/first name), and we keep the most favorable score.\nCompound names and first names: A professional named \u0026ldquo;Loriot De Rouvray\u0026rdquo; can be declared simply as \u0026ldquo;De Rouvray\u0026rdquo;. Using the Jaro-Winkler metric directly would give only 42% similarity; which is very low. To solve this case, we use a custom metric: we count the number of words in common between the declared name and the official one, divided by the smallest number of words in either name. Thus, \u0026ldquo;De Rouvray\u0026rdquo; and \u0026ldquo;Loriot De Rouvray\u0026rdquo; obtain 100% similarity. Indeed, the two names have two words in common (\u0026ldquo;De\u0026rdquo; and \u0026ldquo;Rouvray\u0026rdquo;) and the smallest name also contains two words. The same logic applies to first names, allowing recognition of \u0026ldquo;Jean\u0026rdquo; as a short version of \u0026ldquo;Jean-Luc\u0026rdquo;.\nThe final similarity is then a combination of the different factors described earlier. The calculation breaks down into several steps to obtain an overall similarity score.\nThe objective is to build a robust score that takes into account the different ways a name and first name can be entered.\nEvaluation of similarity for name and first name For the family name, we calculate two distinct scores: the Jaro-Winkler metric and the composition score. We then keep the higher value of the two. This operation is repeated for the first name. We then have a similarity score for the name, and another for the first name.\nCalculate a \u0026ldquo;direct similarity\u0026rdquo; score We add the two scores obtained in the previous step. This total represents our similarity score when we assume that the declaring company did not invert the name and first name of the beneficiary.\nAccount for name/first name inversion To handle cases where the name and first name might have been inverted during entry, we calculate an \u0026ldquo;inverted similarity\u0026rdquo; score. To do this, we compare the declared family name with the official first name, and vice versa, using the Jaro-Winkler metric. Unlike direct similarity, we don\u0026rsquo;t account for a composition score here to allow only one \u0026ldquo;error\u0026rdquo; on the part of the declaring company and limit the risk of getting a good score by chance.\nDetermination of final score The final similarity score is simply the maximum between the direct similarity score and the inverted similarity score.\nRefining the score: contextual variables and confidence threshold # While name and first name similarity is an excellent indicator, it is not always sufficient. Two situations require adjustments to ensure method reliability: handling of homonyms and very poor quality data.\nHandling homonyms: the need for contextual information # The method reaches its limit when faced with true homonyms: two distinct professionals with the same name and first name; that is, the same similarity score. To distinguish between them, it is essential to use additional contextual information:\nPostal code Profession Department of practice However, these variables must be used with caution. A match on postal code should not over-compensate for very different names and first names. We integrate them as slight bonuses to weight the similarity score. A match between the professional directory\u0026rsquo;s postal code and that of the declaration increases the similarity metric by 0.04. Likewise, a profession match adds 0.02 to the similarity. Finally, a match of the department of practice adds 0.01 to the similarity. These values were chosen arbitrarily following data exploration; the objective being to distinguish between two very similar candidates, but insufficient to make a completely incoherent name pass in front of a more relevant name solely thanks to a postal code or profession.\nThe validity threshold: protecting against aberrant data # Sometimes none of the beneficiaries linked to the declared RPPS numbers seem suitable. For example, a declaration for the nurse \u0026ldquo;Karine NOREILS\u0026rdquo; is associated with two RPPS numbers which, according to the directory, correspond to two doctors: \u0026ldquo;Christophe Michiels\u0026rdquo; and \u0026ldquo;Bernard Duclos\u0026rdquo;. The names, first names and professions are so far apart that no match is acceptable.\nTo avoid creating incorrect links in such cases, we have defined a minimum similarity threshold. If the best score obtained does not reach this threshold (arbitrarily set at 1.7), no decision is made. The ambiguity is retained and the case is flagged for further analysis. This safeguard is essential to ensure that only corrections with a high degree of confidence are automated.\nPutting things in perspective and conclusion # The methodology described here is a concrete application of fuzzy matching techniques to a data quality problem. It illustrates that a simple and pragmatic approach, combining a standard similarity algorithm with targeted business rules, makes it possible to resolve a large part of the ambiguities automatically.\nOn all beneficiaries presenting RPPS number ambiguity, this system allows us to resolve more than 95% with a high degree of confidence. The remaining cases, often the most complex, are flagged for further analysis.\nThis approach demonstrates the importance of adapting data science tools to business context. A deep understanding of data and potential sources of error (homonyms, compound names) is essential to build a cleaning solution that is both robust and reliable.\n","date":"18 August 2025","externalUrl":null,"permalink":"/en/articles/clean_rpps_fuzzy/","section":"Articles","summary":"Data quality is a central issue in exploiting public databases. As part of the EurosForDocs project, which aims to bring transparency to financial ties between pharmaceutical companies and healthcare professionals, this issue is particularly critical. The reliability of analyses depends on our ability to unambiguously identify each healthcare professional receiving remuneration or benefits.\n","title":"Applying fuzzy matching for disambiguation of healthcare professionals","type":"articles"},{"content":"La restauration des employés constitue un défi logistique et RH pour les entreprises opérant 24h/24. Alors que les supermarchés, restaurants et boulangeries sont accessibles en journée, les options se raréfient la nuit pour des professions comme les contrôleurs aériens ou les employés d\u0026rsquo;hôtels. Une solution en plein essor est la mise à disposition de frigos connectés. Situés au sein de l\u0026rsquo;entreprise, ils sont régulièrement approvisionnés en produits variés (entrées, plats, desserts, boissons) pour permettre aux employés de se restaurer à toute heure.\nDans l\u0026rsquo;une de mes précédentes entreprises, Foodles, l\u0026rsquo;objectif était de se différencier sur ce marché en proposant des plats frais, préparés par des traiteurs spécialisés et renouvelés quotidiennement. À ce critère de qualité s\u0026rsquo;ajoutait une forte exigence de diversité pour les convives. Chaque frigo contenait entre six et huit recettes différentes de plats principaux, et l\u0026rsquo;intégralité du menu était renouvelée deux fois par semaine pour éviter la lassitude.\nPour les équipes internes, la création de ces menus représentait donc une tâche complexe. Il fallait d\u0026rsquo;abord sélectionner une centaine de recettes pertinentes pour une période de six semaines, puis les répartir entre les différentes demi-semaines. La difficulté principale résidait dans le respect des nombreuses règles métier qui conditionnaient la composition des menus :\nPour satisfaire tous les convives, il était essentiel de garantir une variété au sein de chaque menu. Celui-ci devait inclure des plats carnés et végétariens, à base de pâtes ou de légumes. Un autre aspect de la diversité à prendre en compte était la répartition équilibrée de plats d\u0026rsquo;origines diverses (asiatiques, indiens, etc.) sur l\u0026rsquo;ensemble des périodes.\nLes plats étaient préparés quotidiennement par des traiteurs partenaires, souvent spécialisés dans certains types de recettes. Pour maintenir une relation durable avec eux, il était nécessaire d\u0026rsquo;assurer une certaine stabilité dans les volumes de commandes. Une charge de travail trop fluctuante — avec de nombreuses recettes à préparer une semaine et aucune la suivante — n\u0026rsquo;était pas soutenable pour eux. Enfin une répartition maximale des plats entre les différents fournisseurs permettait une plus grande résilience en cas d\u0026rsquo;imprévus.\nCe processus manuel peut facilement prendre plusieurs heures. Mais au delà de ce temps initial, chaque nouveau contre temps (par exemple une rupture de stock chez un partenaire) nécessite un temps non négligeable pour adapter la répartition initiale à la nouvelle situation.\nL\u0026rsquo;optimisation sous contraintes : une approche algorithmique # Pour automatiser la création de menus, le problème de répartition peut être formulé en utilisant une approche issue de la recherche opérationnelle : l\u0026rsquo;optimisation sous contraintes. Ce domaine des mathématiques appliquées fournit un cadre et des outils pour trouver la meilleure solution possible à un problème, au regard d\u0026rsquo;un objectif donné, parmi un grand nombre de possibilités.\nLa première étape consiste à traduire le problème métier en un modèle mathématique. Un tel modèle se compose de trois éléments clés :\nLes variables de décision : ce sont les inconnues que l\u0026rsquo;on cherche à déterminer. Elles représentent les choix à notre disposition. Dans notre cas, il s\u0026rsquo;agit de savoir si un plat donné est assigné (ou non) à une demi-semaine spécifique.\nLes contraintes : elles définissent les règles que toute solution doit impérativement respecter. Les contraintes traduisent les exigences métier en équations ou inéquations. Par exemple :\nChaque demi-semaine doit contenir exactement 2 plats. Un plat ne peut être proposé qu\u0026rsquo;une seule fois sur toute la période. Deux plats étant trop similaires, c\u0026rsquo;est à dire ayants des caractéristiques (ou tags) en commun ne doivent pas être dans le même menu. La fonction objectif : c\u0026rsquo;est le critère que l\u0026rsquo;on cherche à optimiser (minimiser ou maximiser). Elle quantifie la \u0026ldquo;qualité\u0026rdquo; d\u0026rsquo;une solution. Pour ce problème, un objectif peut être de simplement trouver une répartition qui respecte toutes les règles. On pourrait aussi chercher à maximiser une note de variété, ou à minimiser la répétition de certains ingrédients.\nUne fois le problème formalisé avec ces trois composantes, l\u0026rsquo;étape suivante consiste à utiliser un outil pour le résoudre. C\u0026rsquo;est là qu\u0026rsquo;interviennent des algorithmes spécialisés, appelés solveurs. Un solveur est un moteur de calcul capable d\u0026rsquo;identifier efficacement les solutions les plus pertinentes et d\u0026rsquo;identifier celle qui optimise la fonction objectif, tout en respectant l\u0026rsquo;ensemble des contraintes.\nPour illustrer ce principe, prenons un exemple simple. Imaginons que nous cherchons la valeur de \\(x\\) qui maximise la fonction représentée par la courbe bleue ci-dessous.\nSans aucune contrainte, la solution optimale serait \\(x=3\\). Cependant, si l\u0026rsquo;on impose une contrainte, par exemple que \\(x-1\\) ne doive pas être inférieur à \\(0\\), la solution optimale est ramenée à \\(x=2\\), car c\u0026rsquo;est la meilleure valeur qui respecte cette nouvelle règle. C\u0026rsquo;est ce type de logique qu\u0026rsquo;un solveur applique, mais à des problèmes plus vastes.\nIl existe une grande variété de solveurs, chacun étant spécialisé dans un certain type de problème. Certains sont conçus pour des problèmes quadratiques avec des variables continues (des nombres flottants) et des contraintes linéaires, tandis que d\u0026rsquo;autres peuvent traiter des variables discrètes (comme des booléens) et des contraintes plus complexes.\nLe choix du bon solveur et la formulation du problème dans un format qu\u0026rsquo;il comprend peuvent être complexes. Heureusement, des bibliothèques de plus haut niveau permettent de simplifier ce processus. Dans cet article, nous utiliserons la bibliothèque Python CVXPY. Elle fournit une interface intuitive pour modéliser le problème en termes de variables, de contraintes et d\u0026rsquo;objectif dans le formalisme de numpy. Elle se charge enfin d\u0026rsquo;identifier le solveur adapté et de lui soumettre le problème.\nModélisation du problème # Pour traduire notre problème de planification en un modèle mathématique, il nous faut d\u0026rsquo;abord définir nos variables de décision. L\u0026rsquo;enjeu est de déterminer, pour chaque plat et chaque période, si le plat est assigné ou non.\nUne manière courante de représenter ce type de choix est d\u0026rsquo;utiliser une matrice de décision booléenne. Cette matrice aura les plats en lignes et les périodes en colonnes. Une cellule contiendra la valeur 1 si le plat correspondant est sélectionné pour la période, et 0 sinon.\nPour concrétiser cette approche, commençons par définir nos données d\u0026rsquo;exemple en Python : une liste de plats avec leurs tags (caractéristiques), et une liste de périodes.\nimport numpy as np import pandas as pd meals = sorted( [ (\u0026#34;tagliatelles carbonara\u0026#34;, [\u0026#34;porc\u0026#34;, \u0026#34;viande\u0026#34;, \u0026#34;pate\u0026#34;]), (\u0026#34;lasagnes bolognaise\u0026#34;, [\u0026#34;boeuf\u0026#34;, \u0026#34;viande\u0026#34;, \u0026#34;pate\u0026#34;]), (\u0026#34;cordon bleu - petits pois\u0026#34;, [\u0026#34;poulet\u0026#34;, \u0026#34;viande\u0026#34;]), (\u0026#34;boulette de boeuf - purée\u0026#34;, [\u0026#34;boeuf\u0026#34;, \u0026#34;viande\u0026#34;, \u0026#34;patate\u0026#34;]), (\u0026#34;escalope de veau patate grenaille\u0026#34;, [\u0026#34;viande\u0026#34;, \u0026#34;boeuf\u0026#34;, \u0026#34;patate\u0026#34;]), (\u0026#34;parmentier de canard\u0026#34;, [\u0026#34;viande\u0026#34;, \u0026#34;patate\u0026#34;]), (\u0026#34;saumon riz\u0026#34;, [\u0026#34;poisson\u0026#34;, \u0026#34;riz\u0026#34;]), (\u0026#34;colin carottes\u0026#34;, [\u0026#34;poisson\u0026#34;]), (\u0026#34;wok de crevettes\u0026#34;, [\u0026#34;poisson\u0026#34;, \u0026#34;pate\u0026#34;]), (\u0026#34;tagliatelles forestières\u0026#34;, [\u0026#34;vegetarien\u0026#34;, \u0026#34;pate\u0026#34;]), (\u0026#34;salade nicoise\u0026#34;, [\u0026#34;vegetarien\u0026#34;]), (\u0026#34;risotto aux champignons\u0026#34;, [\u0026#34;vegetarien\u0026#34;, \u0026#34;riz\u0026#34;]), (\u0026#34;ratatouille riz\u0026#34;, [\u0026#34;riz\u0026#34;, \u0026#34;vegetarien\u0026#34;]), ] ) periods = [(f\u0026#34;week{i}\u0026#34;, p) for i in range(3) for p in [\u0026#34;start\u0026#34;, \u0026#34;end\u0026#34;]] repartition_template = pd.DataFrame( # La matrice est initialisée avec des données aléatoires # uniquement pour illustrer la structure que nous cherchons à obtenir. (np.random.rand(len(meals), len(periods)) \u0026gt; 0.5).astype(np.int8), index=[x[0] for x in meals], columns=pd.MultiIndex.from_tuples(periods, names=[\u0026#34;week\u0026#34;, \u0026#34;week_part\u0026#34;]), ) week week0 week1 week2 week_part start end start end start end boulette de boeuf - purée 1 1 0 0 0 0 colin carottes 0 0 0 0 0 1 cordon bleu - petits pois 0 0 1 1 1 0 escalope de veau patate grenaille 0 0 0 1 0 1 lasagnes bolognaise 1 1 0 0 0 0 parmentier de canard 1 0 1 1 0 1 ratatouille riz 0 1 1 1 1 1 risotto aux champignons 1 0 0 1 0 1 salade nicoise 1 1 1 0 1 0 saumon riz 1 0 1 0 1 1 tagliatelles carbonara 1 1 0 0 0 1 tagliatelles forestières 1 1 0 0 1 0 wok de crevettes 1 0 0 1 1 1 Nous allons maintenant traduire cette modélisation en code avec CVXPY. La première étape consiste à définir la variable de décision qui représentera la matrice de répartition des plats. La classe cp.Variable de CVXPY permet de créer une variable de forme donnée, ici de même dimension que notre matrice de répartition. Attention, cp.Variable fonctionne avec des objets de type numpy, mais n\u0026rsquo;est pas compatible directement avec les DataFrames pandas. Il est donc recommandé d\u0026rsquo;utiliser pandas pour manipuler et transformer les données en amont, puis de passer à numpy (via .to_numpy()) pour interfacer avec CVXPY. Dans notre cas, nous précisons que la variable doit être booléenne, c\u0026rsquo;est-à-dire ne prendre que les valeurs 0 ou 1.\nimport cvxpy as cp repartition = cp.Variable(repartition_template.shape, boolean=True) L\u0026rsquo;étape suivante consiste à définir les contraintes fondamentales du problème.\nContrainte 1 : Un nombre fixe de plats par période. Nous souhaitons avoir exactement 2 plats par demi-semaine. Mathématiquement, cela signifie que la somme des valeurs de chaque colonne de notre matrice repartition doit être égale à 2. Contrainte 2 : Un plat ne peut être utilisé qu\u0026rsquo;une fois. Pour éviter de proposer le même plat plusieurs fois, la somme des valeurs de chaque ligne doit être inférieure ou égale à 1. Une valeur de 0 signifie que le plat n\u0026rsquo;a pas été sélectionné, ce qui est attendu puisque nous avons plus de plats que de places. CVXPY permet d\u0026rsquo;exprimer ces contraintes de manière vectorielle, ce qui rend le code à la fois concis et lisible.\nmeal_appear_once = repartition.sum(axis=1) \u0026lt;= 1 two_meals_per_period = repartition.sum(axis=0) == 2 base_constraints = [ two_meals_per_period, meal_appear_once, ] Une fois les variables et les contraintes définies, nous pouvons construire l\u0026rsquo;objet Problem. Cet objet prend deux arguments principaux :\nL\u0026rsquo;objectif : la fonction à minimiser ou maximiser. Pour l\u0026rsquo;instant, nous cherchons simplement à trouver une solution qui respecte les contraintes. On peut alors se contenter d\u0026rsquo;un objectif constant : cp.Minimize(0). Le solveur s\u0026rsquo;arrêtera dès qu\u0026rsquo;il trouvera une configuration valide. Les contraintes : une liste de toutes les règles que la solution doit respecter, c\u0026rsquo;est à dire la liste base_constraints définie plus haut. L\u0026rsquo;appel à prob.solve() lance la résolution. On peut ensuite vérifier le statut du problème et s\u0026rsquo;assurer de la réussite de l\u0026rsquo;optimisation.\nprob = cp.Problem(cp.Minimize(0), constraints=base_constraints) prob.solve() print(\u0026#34;Status: \u0026#34;, prob.status) # Status: optimal La propriété .value de la variable repartition contient la matrice de répartition trouvée par le solveur. Comme l\u0026rsquo;objectif est constant, n\u0026rsquo;importe quelle solution respectant les contraintes est jugée \u0026ldquo;optimale\u0026rdquo;. Le solveur s\u0026rsquo;arrête donc à la première configuration valide qu\u0026rsquo;il trouve, et le résultat peut varier d\u0026rsquo;une exécution à l\u0026rsquo;autre. Le code suivant affiche cette matrice, avec les noms correspondant aux lignes et aux colonnes pour une meilleure lisibilité. On peut y vérifier que nos règles sont bien appliquées : chaque colonne a une somme de 2, et chaque ligne une somme de 1 ou 0.\npd.DataFrame( repartition.value, index=repartition_template.index, columns=repartition_template.columns, ) week week0 week1 week2 week_part start end start end start end boulette de boeuf - purée 0 0 0 0 1 0 colin carottes 0 0 0 0 0 1 cordon bleu - petits pois 1 0 0 0 0 0 escalope de veau patate grenaille 0 0 0 1 0 0 lasagnes bolognaise 1 0 0 0 0 0 parmentier de canard 0 0 1 0 0 0 ratatouille riz 0 0 1 0 0 0 risotto aux champignons 0 0 0 0 0 1 salade nicoise 0 1 0 0 0 0 saumon riz 0 0 0 0 0 0 tagliatelles carbonara 0 0 0 0 1 0 tagliatelles forestières 0 0 0 1 0 0 wok de crevettes 0 1 0 0 0 0 Contraintes métier # Le modèle de base assure une répartition équilibrée, mais il ne garantit pas la diversité au sein d\u0026rsquo;un même menu. Par exemple, il pourrait proposer deux plats de pâtes simultanément. Nous allons maintenant ajouter une contrainte plus fine pour éviter cela : deux plats partageant un même tag (comme \u0026ldquo;pâte\u0026rdquo;, \u0026ldquo;viande\u0026rdquo;, ou \u0026ldquo;poisson\u0026rdquo;) ne doivent pas être assignés à la même période.\nPour implémenter cette règle, nous devons compter, pour chaque période, le nombre de fois où chaque tag apparaît. La contrainte sera respectée si ce nombre est toujours inférieur ou égal à 1 pour tous les tags.\nLa première étape consiste à créer une matrice de correspondance entre les plats et les tags. Cette matrice, que nous nommerons tags_meals, aura les tags en lignes et les plats en colonnes, avec un 1 si un plat est associé à un tag, 0 sinon.\ntags_meals = ( pd.DataFrame.from_records( [{\u0026#34;name\u0026#34;: name} | {t: 1 for t in tags} for name, tags in meals] ) .set_index(\u0026#34;name\u0026#34;) .fillna(0) .astype(int) .sort_index(axis=0) .sort_index(axis=1) .T ) name boulette de boeuf - purée colin carottes cordon bleu - petits pois escalope de veau patate grenaille lasagnes bolognaise parmentier de canard ratatouille riz risotto aux champignons salade nicoise saumon riz tagliatelles carbonara tagliatelles forestières wok de crevettes boeuf 1 0 0 1 1 0 0 0 0 0 0 0 0 patate 1 0 0 1 0 1 0 0 0 0 0 0 0 pate 0 0 0 0 1 0 0 0 0 0 1 1 1 poisson 0 1 0 0 0 0 0 0 0 1 0 0 1 porc 0 0 0 0 0 0 0 0 0 0 1 0 0 poulet 0 0 1 0 0 0 0 0 0 0 0 0 0 riz 0 0 0 0 0 0 1 1 0 1 0 0 0 vegetarien 0 0 0 0 0 0 1 1 1 0 0 1 0 viande 1 0 1 1 1 1 0 0 0 0 1 0 0 Maintenant, comment obtenir le décompte des tags pour chaque période ? C\u0026rsquo;est ici qu\u0026rsquo;intervient une multiplication matricielle.\nLe produit de notre matrice tags_meals (dimensions : nombre de tags x nombre de plats) par la matrice de décision repartition (dimensions : nombre de plats x nombre de périodes) donne une nouvelle matrice, tags_periods, dont les dimensions sont nombre de tags x nombre de périodes.\nChaque cellule de cette matrice résultat contient précisément le nombre d\u0026rsquo;occurrences d\u0026rsquo;un tag donné pour une période donnée, pour une répartition particulière des plats. Le calcul est illustré ci-dessous avec notre matrice repartition_template pour visualiser la forme du résultat.\ntags_meals @ repartition_template week week0 week1 week2 week_part start end start end start end boeuf 2 2 0 1 0 1 patate 2 1 1 2 0 2 pate 4 3 0 1 2 2 poisson 2 0 1 1 2 3 porc 1 1 0 0 0 1 poulet 0 0 1 1 1 0 riz 2 1 2 2 2 3 vegetarien 3 3 2 2 3 2 viande 4 3 2 3 1 3 Pour illustrer l\u0026rsquo;interprétation de cette matrice, prenons la valeur 2 en haut à gauche. Située à l\u0026rsquo;intersection de la ligne boeuf et de la colonne week0/start, elle signifie que dans cette répartition aléatoire, deux plats contenant du bœuf (boulette de boeuf - purée et lasagnes bolognaise) sont assignés à cette période. De même, la valeur 3 sur la ligne vegetarien indique la présence de trois plats végétariens (risotto aux champignons, salade nicoise et tagliatelles forestières) sur cette même période.\nPour traduire la contrainte métier, on a alors besoin d\u0026rsquo;imposer à chaque cellule de valoir au maximum 1. Cela se traduit mathématiquement par : tags_meals @ repartition \u0026lt;= 1. L\u0026rsquo;implémentation dans CVXPY est une traduction directe de cette formule.\nno_same_tag_on_same_period = (tags_meals.values @ repartition) \u0026lt;= 1 Nous pouvons maintenant relancer la résolution du problème en ajoutant cette nouvelle contrainte à notre liste de règles existantes.\nall_constraints = base_constraints + [no_same_tag_on_same_period] prob_business = cp.Problem(cp.Minimize(0), constraints=all_constraints) prob_business.solve() print(\u0026#34;Status: \u0026#34;, prob_business.status) # Status: optimal pd.DataFrame( repartition.value, index=repartition_template.index, columns=repartition_template.columns, ).astype(int) week week0 week1 week2 week_part start end start end start end boulette de boeuf - purée 0 0 0 0 1 0 colin carottes 1 0 0 0 0 0 cordon bleu - petits pois 0 1 0 0 0 0 escalope de veau patate grenaille 0 0 1 0 0 0 lasagnes bolognaise 0 0 0 0 0 1 parmentier de canard 0 0 0 1 0 0 ratatouille riz 0 0 1 0 0 0 risotto aux champignons 0 0 0 0 0 0 salade nicoise 0 0 0 0 0 1 saumon riz 0 1 0 0 0 0 tagliatelles carbonara 1 0 0 0 0 0 tagliatelles forestières 0 0 0 1 0 0 wok de crevettes 0 0 0 0 1 0 En analysant les résultats, on observe que la règle est bien respectée. Par exemple, les plats contenant de la viande ne sont jamais associés à d\u0026rsquo;autres plats de viande. De même, on ne trouve jamais deux plats à base de pâtes ou de pommes de terre dans la même colonne. La diversité au sein de chaque menu est désormais garantie.\nConclusion # L\u0026rsquo;optimisation sous contraintes est une approche efficace pour automatiser des tâches de planification complexes. En exprimant la problématique dans un formalisme mathématique de variable, objectif et contraintes, il devient possible de trouver des solutions optimales tout en garantissant le respect des exigences. La maîtrise de ces techniques de modélisation est un atout pour un data scientist, car elle permet de résoudre de manière structurée une large gamme de problèmes opérationnels.\nRéférences # Modern solvers: Problems well-defined are problems solved CVXPY ","date":"July 28, 2025","externalUrl":null,"permalink":"/articles/optimize_menus/","section":"Articles","summary":"La restauration des employés constitue un défi logistique et RH pour les entreprises opérant 24h/24. Alors que les supermarchés, restaurants et boulangeries sont accessibles en journée, les options se raréfient la nuit pour des professions comme les contrôleurs aériens ou les employés d’hôtels. Une solution en plein essor est la mise à disposition de frigos connectés. Situés au sein de l’entreprise, ils sont régulièrement approvisionnés en produits variés (entrées, plats, desserts, boissons) pour permettre aux employés de se restaurer à toute heure.\n","title":"Automatiser la composition de menus : un cas pratique d'optimisation sous contraintes","type":"articles"},{"content":"","date":"July 28, 2025","externalUrl":null,"permalink":"/tags/optimisation-sous-contrainte/","section":"Tags","summary":"","title":"Optimisation Sous Contrainte","type":"tags"},{"content":"","date":"July 28, 2025","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","date":"July 1, 2025","externalUrl":null,"permalink":"/tags/geospatial/","section":"Tags","summary":"","title":"Geospatial","type":"tags"},{"content":"Imaginons que je sois un consultant souhaitant faire une analyse de marché de la restauration à emporter. Je souhaite connaître pour chaque restaurant le nombre de concurrents dans un rayon de 2km. Je peux par exemple avoir accès à des données similaires à ce dataset Kaggle, qui nous permet d\u0026rsquo;avoir accès à plus de 60k restaurants présents sur UberEats dans tous les États-Unis. En particulier, nous avons notamment accès aux coordonnées GPS de chaque restaurant. Cette donnée va nous permettre de calculer la distance entre deux restaurants, et donc savoir s\u0026rsquo;ils sont potentiellement concurrents. La colonne center a été ajoutée pour permettre l\u0026rsquo;utilisation en polars de la librairie polars-distance\nUne méthode naïve non scalable # Dans un monde small data, le calcul du niveau de concurrence est assez simple. Calculer la distance entre toutes les paires de restaurants et ne garder que celles ayant une distance inférieure à 2km. C\u0026rsquo;est ce que le code suivant implémente en polars. Il est à noter l\u0026rsquo;utilisation de la jointure cross pour créer toutes les paires de restaurants.\ndef filter_by_distance(frame: pl.DataFrame, distance: float) -\u0026gt; pl.DataFrame: return frame.filter( pld.col(\u0026#34;center\u0026#34;).dist.haversine(\u0026#34;center_right\u0026#34;, unit=\u0026#34;km\u0026#34;) \u0026lt;= distance ) def identify_neighbors(frame: pl.DataFrame, distance_treshold: float) -\u0026gt; pl.DataFrame: return ( frame.join(frame, how=\u0026#34;cross\u0026#34;) .filter(col(\u0026#34;id\u0026#34;) != col(\u0026#34;id_right\u0026#34;)) .pipe(filter_by_distance, distance_treshold) ) possible_neighbors = identify_neighbors(restaurants.head(10000), 2) possible_neighbors.shape # (334626, 10) Cette technique a deux limitations principales.\nLe nombre de calculs de distance à effectuer croît quadratiquement avec le nombre de restaurants. Ici avec seulement 10k restaurants (pour un dataset de 63.5k), c\u0026rsquo;est déjà 100 millions de paires qui doivent être testées. Du fait de sa lenteur (92 secondes) et de sa forte consommation de RAM, ce type d\u0026rsquo;approche peut coûter très cher sur des plateformes de cloud computing. D\u0026rsquo;ailleurs, ma machine sature en RAM lorsque je tente d\u0026rsquo;appliquer l\u0026rsquo;analyse sur les 63.5k restaurants. Enfin à partir de 66k restaurants, polars aurait levé une exception car sa version de base semble limitée à 2^32 lignes dans un DataFrame.\nL\u0026rsquo;immense majorité des distances calculées le sont pour des paires absurdes. Par exemple, cette technique calcule toutes les paires contenant un restaurant à New York et un à Los Angeles ; restaurants qui sont de manière évidente trop éloignés les uns des autres pour être des concurrents. Dans notre cas, seules 335k paires de concurrents existent effectivement dans notre dataset, soit 0.3% de toutes les paires testées. Les calculs de distance pour ces paires représentent donc une pure perte de temps et de coût d\u0026rsquo;infrastructure.\nLa méthode des bloqueurs pour réduire la complexité # La solution de ce problème est présente dans sa description. En réduisant le nombre de paires absurdes, on va pouvoir accélérer la recherche de concurrents sans perdre de données pertinentes. Il serait alors pratique de savoir avant de calculer la distance entre deux restaurants s\u0026rsquo;ils ont une chance même minime d\u0026rsquo;être concurrents.\nOn peut par exemple découper les États-Unis en petites zones de 0.1 degré de latitude et de longitude de côté. Cela correspond grossièrement à des zones de 10km de haut pour 5km de large. Deux restaurants qui ne sont pas dans des régions adjacentes n\u0026rsquo;ont alors aucune chance d\u0026rsquo;être concurrents. Deux restaurants dans des zones adjacentes peuvent encore être à plus de 20km l\u0026rsquo;un de l\u0026rsquo;autre. Il est donc toujours nécessaire de calculer la distance entre restaurants pour définir s\u0026rsquo;ils sont concurrents mais le nombre de combinaisons possibles est alors beaucoup plus faible.\nD\u0026rsquo;un point de vue technique, on peut alors remplacer une jointure cross très coûteuse par plusieurs jointures inner bien plus optimisées. En reformattant la fonction identify_neighbors comme ci-dessous, nous réduisons le nombre de paires testées à seulement 4 millions (soit 4 % de toutes les paires possibles). Notre dataset à 10 000 restaurants est donc traité en 207ms au lieu de 92s et on retrouve au final exactement les 334 626 restaurants concurrents. On peut alors même traiter l\u0026rsquo;intégralité des 63.5k restaurants pour identifier 4.2 millions de paires en moins de 4s.\ndef add_restaurant_region(frame: pl.DataFrame) -\u0026gt; pl.DataFrame: return frame.with_columns( (col(\u0026#34;lng\u0026#34;) * 10).cast(pl.Int64).alias(\u0026#34;region_lng\u0026#34;), (col(\u0026#34;lat\u0026#34;) * 10).cast(pl.Int64).alias(\u0026#34;region_lat\u0026#34;), ) def partitionned_identify_neighbors( frame: pl.DataFrame, distance_treshold: float ) -\u0026gt; pl.DataFrame: frame = add_restaurant_region(frame) neighbors = [] for lat_shift in range(-1, 2): for lng_shift in range(-1, 2): tmp = frame.with_columns( col(\u0026#34;region_lat\u0026#34;) + lat_shift, col(\u0026#34;region_lng\u0026#34;) + lng_shift ) joined = ( frame.join(tmp, on=[\u0026#34;region_lat\u0026#34;, \u0026#34;region_lng\u0026#34;]) .filter(col(\u0026#34;id\u0026#34;) != col(\u0026#34;id_right\u0026#34;)) .drop([\u0026#34;region_lat\u0026#34;, \u0026#34;region_lng\u0026#34;]) .pipe(filter_by_distance, distance_treshold) ) neighbors.append(joined) return pl.concat(neighbors) partitioned = partitionned_identify_neighbors(restaurants.head(10000), 2000) partitioned.shape # (334626, 10) Conclusion # La jointure de table grâce à des règles métiers au lieu de colonnes d\u0026rsquo;identifiant permet une grande diversité d\u0026rsquo;applications. Cependant, ce type de jointure peut s\u0026rsquo;avérer très coûteux du fait du nombre de combinaisons possibles et qu\u0026rsquo;une part significative des calculs à effectuer n\u0026rsquo;apportent aucune valeur. Le découpage des États-Unis en petites zones a permis de se rapprocher d\u0026rsquo;une situation avec des colonnes d\u0026rsquo;identifiant. On a alors pu utiliser les optimisations liées à ce type de jointure pour mener notre analyse 500x plus vite.\nC\u0026rsquo;est donc à travers une compréhension fine du problème et un peu de créativité que nous avons pu lever les blocages liés au temps de calcul de cette analyse.\nPour aller plus loin # D\u0026rsquo;autres data scientists ont partagé leurs solutions à des problèmes similaires.\nWhat\u0026rsquo;s in a Name? Fast Fuzzy String Matching # Dans leur présentation au Midwest.io 2015, deux data scientists ont présenté un problème conceptuellement plus simple : identifier les noms similaires entre une liste de 10 millions et une autre de 40 000 ? Avec 400 milliards de paires à comparer, le calcul de la similarité Jaro-Winkler pour chaque paire prendrait 13 jours. À travers une compréhension profonde de cette similarité et des choix de structure de données pertinents, ils ont réduit ce calcul à 5 min.\nLeur solution repose sur deux piliers :\nCompréhension de Jaro-Winkler : Ils ont réalisé que l\u0026rsquo;on pouvait tordre la formule pour obtenir une borne supérieure basée uniquement sur les caractères partagés. En ne calculant que cette borne, ils ont pu écarter massivement et rapidement les paires non pertinentes sans jamais avoir à effectuer le calcul complet, bien plus coûteux, de la similarité.\nOptimiser matériellement : Pour rendre ce filtrage quasi-instantané, ils ont utilisé une structure de données astucieuse : le bitset. Chaque mot est représenté par une séquence de bits où chaque bit correspond à une lettre de l\u0026rsquo;alphabet. Si le mot contient la lettre, le bit est à 1, sinon à 0. Cette représentation permet au processeur de comparer les ensembles de lettres de deux mots en une seule instruction, offrant un gain de temps considérable.\n","date":"July 1, 2025","externalUrl":null,"permalink":"/articles/finding_neighors/","section":"Articles","summary":"Imaginons que je sois un consultant souhaitant faire une analyse de marché de la restauration à emporter. Je souhaite connaître pour chaque restaurant le nombre de concurrents dans un rayon de 2km. Je peux par exemple avoir accès à des données similaires à ce dataset Kaggle, qui nous permet d’avoir accès à plus de 60k restaurants présents sur UberEats dans tous les États-Unis. En particulier, nous avons notamment accès aux coordonnées GPS de chaque restaurant. Cette donnée va nous permettre de calculer la distance entre deux restaurants, et donc savoir s’ils sont potentiellement concurrents. ","title":"Optimisation de jointures géospatiales : le partitionnement pour éliminer les calculs inutiles","type":"articles"},{"content":"","date":"July 1, 2025","externalUrl":null,"permalink":"/tags/polars/","section":"Tags","summary":"","title":"Polars","type":"tags"},{"content":"","date":"May 28, 2025","externalUrl":null,"permalink":"/tags/transparence/","section":"Tags","summary":"","title":"Transparence","type":"tags"},{"content":"","date":"27 May 2025","externalUrl":null,"permalink":"/en/tags/data-quality/","section":"Tags","summary":"","title":"Data Quality","type":"tags"},{"content":"","date":"27 May 2025","externalUrl":null,"permalink":"/en/tags/eurosfordocs/","section":"Tags","summary":"","title":"EurosForDocs","type":"tags"},{"content":" A scandal that changed everything # In 2010, pulmonologist Irène Frachon publishes the book Mediator 150 mg: How many deaths? and triggers the Mediator scandal in France. From 1976 to 2009, this amphetamine-like drug was prescribed as an appetite suppressant even though its authorization was limited only to the treatment of type 2 diabetes. The consequences were catastrophic: approximately 2,000 deaths and many patients suffering from serious side effects, particularly cardiovascular lesions.\nFaced with this health disaster, a law relating to strengthening pharmaceutical safety and health products was passed in 2011 to impose a new obligation on pharmaceutical laboratories and healthcare sector companies: publicly declare any financial payment or benefit in kind granted to healthcare professionals, hospitals or health-related associations. This measure aims to make visible the conflicts of interest that could influence medical practices. A government platform, Transparence Santé, was launched to centralize these declarations and make them available to the public in the form of open data.\nTransparency that is difficult to exploit # Poor data quality # While the intention behind the Transparence Santé platform is commendable and unique in Europe, significant gaps make it difficult for citizens to use it. Imagine you\u0026rsquo;re looking for information about a doctor named \u0026ldquo;Leurent\u0026rdquo;. Here\u0026rsquo;s what you\u0026rsquo;d see on the government platform:\nOne problem immediately stands out: several doctors appear multiple times in the results, with slight variations. Duplicate entries exist due to minor spelling differences, nearby cities mentioned, or simple data entry errors. For someone who wants to know the conflicts of interest of a specific person, it becomes difficult to get a complete picture of the situation.\nThis problem is symptomatic of a lack of best practices in database creation, both at the platform level and among declaring laboratories. Yet all beneficiaries of benefits and remuneration have a unique national identifier: the RPPS for healthcare professionals and SIREN for associations and other legal entities. It is then easy to use these identifiers and their respective directories to ensure consistency in beneficiary data. Unfortunately, only 50% of declarations actually have an identifier. A 2022 platform update did increase RPPS usage to 90%; however, it did not impact data relating to associations, which receive most benefits and remuneration.\nLack of ergonomics # Let\u0026rsquo;s continue our example by clicking on the page for Dr. Bernard Leurent, who does not appear to be duplicated. We then arrive at a page that simply lists all declarations relating to this beneficiary in list form.\nTo simply know the total amount received by the beneficiary, it is necessary to download declarations in CSV format and use Excel to sum the amounts. It should be noted that it may be necessary to combine multiple spreadsheets if the beneficiary has multiple accounts. This information search can quickly become tedious. Understanding the distribution by company is made even more complicated by data quality, as a company can declare through different accounts and subsidiaries that don\u0026rsquo;t necessarily share the same name.\nThe Transparence Santé database thus falls into a paradoxical situation. While technically offering freely accessible data, data quality and user interface are significant barriers to the use of this data by civil society.\nEurosForDocs: a solution for genuine transparency # Faced with this situation, the association EurosForDocs was created by two Transparence Santé users to try to improve things. Based on public data from Transparence Santé, EurosForDocs pursues three main objectives:\nOffer a user-friendly exploration platform: Available for free at eurosfordocs.fr, it allows everyone to easily consult the conflicts of interest between pharmaceutical laboratories and various beneficiaries. Clean and improve data: The team works to normalize and even correct data. Identifying and merging duplicates among beneficiaries plays an important role in database usability. Support researchers and journalists: EurosForDocs offers its expertise to help those who want to analyze this data in depth, thus contributing to public debate on healthcare transparency. Some examples of contributions are given at the end of the article. To meet the association\u0026rsquo;s first objective, a dashboard allows you to quickly get a general picture of the situation. The result for Dr. Bernard Leurent automatically offers several visualizations: total amount received, breakdown of payments by company, evolution of amounts over time, and reasons for payments. For more in-depth analysis, the details of declarations are also available and downloadable.\nA data processing pipeline to transform data # The Transparence Santé database suffers from many data quality issues. The core of EurosForDocs\u0026rsquo;s technical challenge is therefore to correct these data to make them more reliable and usable. To do this, we have implemented an automated process that runs every morning. It starts by downloading the latest version of Transparence Santé, then passes it through several cleaning and improvement steps. Finally, the cleaned data is made available on our site through our dashboard or directly as a CSV file. Technically, our solution relies on Python code that orchestrates SQL queries that transform the data.\nDuckDB is used as the data processing engine. This SQL variant has several characteristics useful for this project:\nIt is optimized for massive processing. It does not require special infrastructure: data is stored locally in simple files. It can adapt to small machines: so you can use the cheapest cloud servers. The use of this technology allows us to efficiently process millions of declarations, at low cost, and maintain low latency on our dashboard.\nFor transparency purposes, our source code is entirely public. Anyone with Python and SQL skills can download the code, run data processing on their machine, and audit the various transformations.\nOur data correction process breaks down mainly into 4 parts.\nCompany deduplication: We group together different subsidiaries and multiple accounts of the same company to obtain a consolidated view. Beneficiary deduplication: We identify and merge multiple entries that correspond to the same healthcare professional or organization. Reason normalization: We standardize the stated reasons for payments to allow for coherent analysis. Linking declarations: We improve the connections between different payments and the agreements in which they should be included. An almost functional company deduplication system # In the Transparence Santé system, the same declaring company can appear under several different identities. Each subsidiary can make its own declarations, sometimes even through multiple separate accounts. These different accounts most often have different names. It then becomes more complex to understand the stakes of conflicts of interest when the same laboratory appears under several variants. In theory, the government platform has provided a deduplication mechanism. It is possible to declare that a company account belongs to a grouping by providing the identifier of a reference account (or parent company). Merging accounts linked to the same parent company should normalize the names of declaring companies. You then get more understandable data. Unfortunately, declaring companies lack rigor in using this mechanism. After merging linked accounts, many duplicates persist in the database and require cleaning.\nThe medical sector only brings together relatively few companies, with only 4,850 company accounts declared in Transparence Santé. Moreover, companies are expected to reuse existing declaration accounts as much as possible. Creating new accounts should be occasional: subsidiary creation or new service, staff turnover, etc\u0026hellip; Under these conditions, a semi-manual check of duplicates is still possible.\nThe following image shows a working document for manual deduplication. For each company, the stated parent company is documented in column E. The EurosForDocs team can assign a reference account to a declaring company in column H. The blue highlighting shows, for example, the different subsidiaries of the 3M group, some of which were automatically linked to the French parent company and others considered as independent companies. Finally, through this mixed deduplication system, nearly 900 accounts are merged.\nBeneficiary deduplication: the war of the clones # The greatest technical challenge for EurosForDocs concerns the unique identification of beneficiaries in the database. Unlike companies which number in the thousands, we must here process more than 26 million potentially duplicate declared beneficiaries. In theory, the solution seems simple: each healthcare professional has an official identification number (RPPS or ADELI) and each organization has a business number (SIREN) or association number (RNA). Unfortunately, in practice, these identifiers are rarely correctly entered in declarations. Our mission is therefore to try to assign an official identifier to each declaration that lacks one.\nOur analysis reveals two distinct situations:\nNatural persons (doctors, nurses, etc.): We have several elements to identify them (name, first name, profession, postal code). We can cross-reference this data with the national directory of healthcare professionals to try to assign an RPPS or ADELI number to each beneficiary. Legal entities (associations, hospitals, etc.): Only the name and sometimes the SIREN or RNA number are available. Organization names being much less standardized than family names, their automatic deduplication remains a challenge we have not yet solved. However, a manual deduplication system is in place for occasional needs. Beneficiary reduction by declaration consistency # For each new declaration concerning the same beneficiary, companies must repeat the information concerning them. We can then consider that a company declaring the same name, first name, profession and postal code of beneficiary between two declarations refers to the same entity. This information then defines a beneficiary account, identified by an efd_id number. We have however observed that for the same beneficiary account, different identifiers can be entered. For example, the account corresponding to Jean Crochet has two different RPPS numbers.\nWe then analyzed these accounts in detail. Using the directories dedicated to each type of identifier, we were able to compare the official information linked to each identifier with those declared in Transparence Santé. Consistently, only one of the identifiers matches the directory values. By defining a similarity notion based on name, first name, profession and postal code, we can automatically identify absurd RPPS numbers. In Jean Crochet\u0026rsquo;s case, one of the RPPS actually corresponds to Nathalie Bourgeois; which leads to a similarity score well below that corresponding to the correct RPPS. We then clean the database to keep only the correct identifiers.\nHow to identify a healthcare professional among duplicates? # Since companies can freely enter information about beneficiaries, without an imposed format, many variations and errors are present for the same person. EurosForDocs has defined a 3-step strategy to try to group duplicate beneficiary accounts into a single entity.\nAssign missing identifiers: For beneficiaries without an RPPS number, we try to match their information with the official directory of health professionals. We start with the simplest cases (exact matching of all fields) before gradually relaxing our criteria to handle more ambiguous cases, such as name/first name inversions or compound names partially declared. It should be noted that we do not assign an RPPS if the criteria identify multiple different professionals in the directory.\nGroup similar accounts: Some beneficiaries cannot be linked to an official identifier but share the same information. For example, two beneficiaries who share the same name, first name and profession and who have no RPPS are considered duplicates. This method is less reliable but only applies to accounts for which identification based on the health directory has failed.\nMerge all duplicates: The two previous steps made it possible to create links between different accounts. Step 1 creates indirect links (via RPPS, SIREN, etc.). Step 2 directly links two accounts. A social network processing algorithm will then group all accounts that belong to the same isolated community. Each community is then considered a unique beneficiary and all accounts that are part of it will be merged. In the following example, the beneficiary accounts (in light blue) create three distinct communities through the links between them (accounts 10 and 3 at the bottom of the image) or their link to an RPPS or ADELI account.\nThis deduplication strategy allows us to significantly reduce the number of duplicates. From over 6 million healthcare professional accounts, 1.6 million remain after deduplication. There is probably still a significant amount of duplicates among our final beneficiaries since 780,000 accounts currently have no identifier.\nThe challenge of normalizing payment reasons # Originally, pharmaceutical companies documented the reasons for their payments to healthcare professionals in a simple free-text field. This lack of standardization made data analysis practically impossible. Reasons varied considerably from one declaration to another: ranging from detailed descriptions of specific conferences to simple mentions like \u0026ldquo;meal\u0026rdquo;, or even remaining completely empty. To remedy this situation, a 2022 update to the Transparence Santé platform introduced a nomenclature of 48 reason values. However, despite this improvement, many companies bypass this standardization by simply selecting the \u0026ldquo;OTHER\u0026rdquo; category and then entering their custom descriptions in a supplementary field. Some \u0026ldquo;OTHER\u0026rdquo; reasons even exactly correspond to one of the 48 official categories. The following image shows us the variety of \u0026ldquo;OTHER\u0026rdquo; reasons that we seek to standardize. Faced with this challenge, EurosForDocs developed an approach combining manual processing and automated keyword analysis. We go from 18 million undisclosed reasons to 1.2 million.\nLinking payments to contracts: more accurate accounting # In the system for disclosing conflicts of interest, pharmaceutical laboratories must first declare a contract (agreement) with a healthcare professional, specifying the total planned amount, then separately declare each actual payment made under this contract. We thus have a problem of double counting amounts: once in the agreement as a projected amount and once for the actual payment. To avoid this double counting, EurosForDocs deducts the actual amounts of remuneration and related benefits from the amounts of agreements. The final amount of an agreement that we display is then the remainder, or amount remaining to be spent of the agreement.\nTo obtain the most accurate possible view of these remainders (and thus reduce the risk of double counting), we must ensure that all actual payments are indeed linked to a contract. In practice, many payments appear without a link to their initial contract. EurosForDocs then tries to link orphaned remuneration and benefits to agreements being more permissive about the declaring company and beneficiary account.\nConclusion # The Transparence Santé platform is a major step forward towards greater transparency in the pharmaceutical industry. However, data quality limits the potential of the platform. Initiatives like EurosForDocs show that it is possible to transform raw and unreliable data into clear and exploitable information. But this requires meticulous cleaning work and a rigorous approach. This project illustrates not only the technical challenges of data management, but also the importance of making this information accessible and understandable to all; to ensure genuine transparency in the healthcare field. In an increasingly data-dependent world, it is essential that we don\u0026rsquo;t just make data available, but also make it usable, understandable and reliable.\nExamples of collaborations # Flu vaccine: geriatric societies\u0026rsquo; recommendation lacks transparency\nSex and gaming addictions: Parkinson\u0026rsquo;s patients claim they were duped by a lab\nBartering and lobbying: behind Sanofi\u0026rsquo;s billion-euro announcement\nAdditional resources # The Mediator scandal / Myth-theories - Fact or Myth ","date":"27 May 2025","externalUrl":null,"permalink":"/en/projets/eurosfordocs/","section":"Projets","summary":"A scandal that changed everything # In 2010, pulmonologist Irène Frachon publishes the book Mediator 150 mg: How many deaths? and triggers the Mediator scandal in France. From 1976 to 2009, this amphetamine-like drug was prescribed as an appetite suppressant even though its authorization was limited only to the treatment of type 2 diabetes. The consequences were catastrophic: approximately 2,000 deaths and many patients suffering from serious side effects, particularly cardiovascular lesions.\n","title":"EurosForDocs: Strengthening Transparency in Healthcare","type":"projets"},{"content":"","date":"27 May 2025","externalUrl":null,"permalink":"/en/tags/open-data/","section":"Tags","summary":"","title":"Open Data","type":"tags"},{"content":"","date":"27 May 2025","externalUrl":null,"permalink":"/en/projets/","section":"Projets","summary":"","title":"Projets","type":"projets"},{"content":"","date":"27 May 2025","externalUrl":null,"permalink":"/en/tags/transparency/","section":"Tags","summary":"","title":"Transparency","type":"tags"},{"content":"Dans notre monde numérique, les données sont partout. Des grandes entreprises aux petites associations, chacun doit aujourd\u0026rsquo;hui composer avec cette nouvelle réalité. Mais comment les petites structures peuvent-elles tirer parti de cette abondance de données sans les ressources des géants du numérique ?\nUn séminaire pour comprendre les enjeux de l\u0026rsquo;inflation des données # L\u0026rsquo;association Aristote a organisé le 11 février 2025 un séminaire intitulé Inflation des données numériques : que faire ? est-ce viable ?. Alors que la plupart des intervenants se concentraient sur les solutions Big Data, j\u0026rsquo;ai choisi d\u0026rsquo;aborder la problématique sous l\u0026rsquo;angle des petites structures.\nEurosForDocs : une petite structure en missison # Pour illustrer cette approche, j\u0026rsquo;ai présenté le cas de l\u0026rsquo;association EurosForDocs. Celle-ci s\u0026rsquo;est donnée pour mission d\u0026rsquo;améliorer la transparence et réduire les risques de conflit d\u0026rsquo;intérêt dans le domaine de la santé.\nDepuis le scandale du Médiator, les laboratoires pharmaceutiques doivent déclarer publiquement les sommes versées aux professionnels de santé. Ces informations sont disponibles en open data sur le site Transparence Santé. Cependant, la qualité et l\u0026rsquo;accessibilité des données ne permettent pas aux personnes sans compétences data de réellement les exploiter.\nEurosForDocs intervient alors comme un intermédiaire : tous les matin les données sont récupérées, nettoyées, et mise à disposition sur sont site à travers des tableaux de bords. Une description plus détaillée de leur action est proposée dans cet autre article.\nUn monde d\u0026rsquo;abondance pour les données # Aujourd\u0026rsquo;hui, l\u0026rsquo;accès aux données n\u0026rsquo;a jamais été aussi facile. Des plateformes gouvernementales telles data.gouv proposent plusieurs dizaines de milliers de jeux de données sur une très grande variété de domaines. Des institutions internationales telles que l\u0026rsquo;OMS et l\u0026rsquo;ONU mettent également à disposition du public des données sectorielles. Ces données officielles peuvent également être complémentées par des plateformes telles que Kaggle ou par de la récupération en direct sur certains sites internets.\nCette abondance de données représente une opportunité sans précédent pour toutes les organisations, y compris les plus petites. Cependant, pour les exploiter efficacement, il faut surmonter plusieurs défis techniques et méthodologiques que nous allons explorer.\nLa complexité de la mise en relation des données # La véritable valeur des données émerge souvent de leur mise en relation, c\u0026rsquo;est-à-dire de la capacité à combiner différentes manières d\u0026rsquo;aborder le même sujet d\u0026rsquo;étude. Cependant, cette interconnexion soulève des défis majeurs. Chaque source de données suit ses propres conventions, ce qui peut compliquer leur utilisation conjointe.\nLe cas d\u0026rsquo;EurosForDocs illustre parfaitement cette problématique. En théorie, tous les médecins disposent d\u0026rsquo;un numéro d\u0026rsquo;identification national (RPPS) et les laboratoires d\u0026rsquo;un numéro d\u0026rsquo;entreprise SIREN. Ces identifiants devraient faciliter la liaison entre différentes bases de données : le même médecin devrait apparaître partout avec le même identifiant. En pratique, les laboratoires qui déclarent des liens d\u0026rsquo;intérêt avec des médecins ne remplissent pas systématiquement le champ RPPS. Il devient alors complexe de déterminer si deux déclarations font référence à la même personne ou non.\nUn des principaux apports d\u0026rsquo;EurosForDocs à la transparence dans la santé consiste justement à réattribuer un RPPS à une grande part des professionnels de santé mentionnés dans la base Transparence Santé. Grâce à un meilleur taux d\u0026rsquo;identification via RPPS, le nombre de doublons dans la base est significativement réduit. Au final, les analyses aboutissent à des chiffres beaucoup plus fiables.\nLe défi des données non structurées # La complexité ne s\u0026rsquo;arrête pas là. Au-delà des problèmes d\u0026rsquo;interconnexion, certaines bases de données posent des défis supplémentaires car elles n\u0026rsquo;ont pas été conçues dans une optique d\u0026rsquo;analyse. C\u0026rsquo;est particulièrement le cas des bases contenant des données déclaratives libres, où les contributeurs peuvent saisir des informations sans contraintes strictes.\nDans la base Transparence Santé, cette problématique est flagrante. Les laboratoires doivent indiquer un motif pour chaque déclaration de lien d\u0026rsquo;intérêt, mais ce champ de saisie libre a généré des millions de formulations différentes pour des motifs similaires. Chaque entreprise renseigne ces informations selon sa propre logique, créant un véritable casse-tête pour l\u0026rsquo;analyse.\nFace à cette hétérogénéité, EurosForDocs a développé une solution de normalisation. L\u0026rsquo;association regroupe tous ces motifs disparates en catégories cohérentes et compréhensibles, permettant enfin une analyse fiable des relations d\u0026rsquo;intérêt dans le secteur de la santé.\nUne solution technologique adaptée # Face à ces défis, la technologie a évolué pour répondre aux besoins des petites structures, mais également pour réduire les coûts des moyennes entreprises. Historiquement, deux approches principales se sont développées pour traiter les données. La première, adaptée aux petits volumes (moins de quelques gigaoctets), permet de charger l\u0026rsquo;intégralité des données en mémoire et de les traiter directement sur un ordinateur standard. La seconde, le Big Data, découpe les données en petits morceaux pour les traiter sur différentes machines, permettant ainsi de gérer des volumes quasi illimités.\nCependant, le Big Data présente des inconvénients majeurs pour les petites structures. Il nécessite des compétences techniques spécialisées pour mettre en place l\u0026rsquo;infrastructure et un budget conséquent pour les calculs. Pour une association disposant de peu de bénévoles et de moyens financiers limités comme EurosForDocs, ces contraintes peuvent rapidement constituer un obstacle majeur à son activité.\nDepuis quelques années, une troisième approche a émergé, spécialement conçue pour les volumes intermédiaires (jusqu\u0026rsquo;à quelques téraoctets). Cette solution repose sur un constat pragmatique : la plupart des organisations n\u0026rsquo;ont pas besoin de traiter des volumes de données astronomiques. Un disque dur commercial suffit généralement à stocker l\u0026rsquo;ensemble de leurs données.\nLa technologie DuckDB illustre parfaitement ce nouveau paradigme. Côté stockage, toutes les données sont regroupées dans un unique fichier compressé directement sur le disque dur. En arrière-plan, DuckDB gère automatiquement le découpage des données en morceaux suffisamment petits pour tenir dans la mémoire disponible. Ces fragments sont ensuite traités successivement par la machine pour produire le résultat final du calcul. Aucune configuration particulière n\u0026rsquo;est nécessaire pour bénéficier de ce fonctionnement optimisé. Cette technologie s\u0026rsquo;intègre parfaitement dans l\u0026rsquo;écosystème data existant : la manipulation des données se fait via le langage standard SQL et des outils d\u0026rsquo;intégration sont disponibles dans de nombreux langages de programmation (notamment Python).\nCette solution intermédiaire offre effectivement le meilleur des deux mondes : la simplicité d\u0026rsquo;utilisation des petits volumes et la capacité à traiter des données plus importantes que la mémoire disponible. Elle permet ainsi aux petites structures d\u0026rsquo;exploiter efficacement leurs données sans investissements majeurs en infrastructure ou en expertise technique. Chez EurosForDocs, l\u0026rsquo;adoption de DuckDB a permis de complexifier significativement les analyses, tout en continuant d\u0026rsquo;utiliser les serveurs OVH les plus modestes pour le traitement journalier et ainsi maîtriser les coûts d\u0026rsquo;infrastructure.\nConclusion : la démocratisation de l\u0026rsquo;accès aux données # Notre époque se caractérise par une abondance inédite de données accessibles, mais cette richesse reste largement sous-exploitée par les petites structures face aux défis techniques complexes d\u0026rsquo;interconnexion, d\u0026rsquo;hétérogénéité des formats et de données non structurées. L\u0026rsquo;émergence du medium data, illustrée par des technologies comme DuckDB, change la donne en permettant de traiter des volumes significatifs sans la complexité du Big Data. Le cas d\u0026rsquo;EurosForDocs démontre concrètement cette démocratisation : en transformant des données gouvernementales brutes en analyses accessibles, l\u0026rsquo;association prouve qu\u0026rsquo;une petite structure peut créer un impact social majeur avec peu de moyens.\nCette démocratisation redessine le paysage de l\u0026rsquo;innovation sociale en permettant aux citoyens organisés de s\u0026rsquo;emparer des enjeux de transparence et de créer des outils au service de l\u0026rsquo;intérêt général. L\u0026rsquo;association Data For Good en est d\u0026rsquo;ailleurs un très bon exemple. À l\u0026rsquo;heure où l\u0026rsquo;information fiable devient cruciale pour notre démocratie, les petites structures disposent enfin des moyens techniques pour jouer un rôle déterminant dans ce défi collectif.\n","date":"February 16, 2025","externalUrl":null,"permalink":"/conferences/aristote_data/","section":"Conférences","summary":"Dans notre monde numérique, les données sont partout. Des grandes entreprises aux petites associations, chacun doit aujourd’hui composer avec cette nouvelle réalité. Mais comment les petites structures peuvent-elles tirer parti de cette abondance de données sans les ressources des géants du numérique ?\n","title":"Le medium data : quels enjeux pour les petites structures?","type":"conferences"},{"content":"","externalUrl":null,"permalink":"/en/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/en/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/en/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"Articles, projets et conférences.\n","externalUrl":null,"permalink":"/all_content/","section":"Tous les articles","summary":"Articles, projets et conférences.\n","title":"Tous les articles","type":"all_content"}]