
[{"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 contiuer à traiter ques 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 poaur 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 réprésentant des déclarations. Ainsi le premier élément compris entre {} concerce 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 simples : 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 aidier; 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 apparaitre 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 chaines 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’ensemble des subventions d’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":"1 avril 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":"","date":"1 avril 2026","externalUrl":null,"permalink":"/","section":"Data Diffusion","summary":"","title":"Data Diffusion","type":"page"},{"content":"","date":"1 avril 2026","externalUrl":null,"permalink":"/projets/","section":"Projets","summary":"","title":"Projets","type":"projets"},{"content":"Retrouvez ici le résumé de mes différentes conférences.\n","date":"23 mars 2026","externalUrl":null,"permalink":"/conferences/","section":"Conférences","summary":"Retrouvez ici le résumé de mes différentes conférences.\n","title":"Conférences","type":"conferences"},{"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":"23 mars 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":"14 mars 2026","externalUrl":null,"permalink":"/tags/data-quality/","section":"Tags","summary":"","title":"Data Quality","type":"tags"},{"content":"","date":"14 mars 2026","externalUrl":null,"permalink":"/tags/duckdb/","section":"Tags","summary":"","title":"DuckDB","type":"tags"},{"content":"","date":"14 mars 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":"14 mars 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":"","date":"14 mars 2026","externalUrl":null,"permalink":"/tags/open-data/","section":"Tags","summary":"","title":"Open Data","type":"tags"},{"content":"","date":"14 mars 2026","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"4 mars 2026","externalUrl":null,"permalink":"/articles/","section":"Articles","summary":"","title":"Articles","type":"articles"},{"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.\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.\nLes 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.\n","date":"4 mars 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":"Présentation effectuée dans le cadre du meetup Bordeaux ApérOps le 11 février 2026.\nTélécharger les slides (PDF)\nL\u0026rsquo;enjeu de la transparence dans la santé # Le scandale du Mediator # Le Mediator est un médicament dérivé de l\u0026rsquo;amphétamine, commercialisé par le laboratoire Servier comme antidiabétique à partir de 1976. Au-delà de son cadre officiel d\u0026rsquo;utilisation, il a toutefois été massivement prescrit comme coupe-faim pendant plus de trente ans. Durant toutes ces années, il aurait entraîné la mort de plus de 1500 personnes et créé de graves pathologies à des milliers d\u0026rsquo;autres.\nLe scandale a éclaté en 2009, lorsque la pneumologue Irène Frachon publie le livre Mediator 150 mg : combien de morts ?.\nTransparence Santé # Suite à ce scandale qui avait mis en lumière des conflits d\u0026rsquo;intérêts dans les organismes de contrôle, une loi a été votée pour imposer aux laboratoires la déclaration toute rémunération ou avantage en nature versé à des professionnels de santé ou tout autre acteur lié à la santé (associations, entreprises). Toutes ces déclarations ont été mises à disposition du public à travers une plateforme d\u0026rsquo;open data Transparence Santé.\nUne transparence floue # Bien que l\u0026rsquo;on puisse considérer la transparence comme acquise grâce à la disponibilité des données, l\u0026rsquo;objectif n\u0026rsquo;est cependant pas atteint. La faible qualité des données, principalement le manque de normalisation et les doublons, rendent l\u0026rsquo;exploitation des données très compliquée pour toute personne sans compétences data.\nUne simple recherche d\u0026rsquo;un médecin traitant peut rapidement tourner au casse-tête. L\u0026rsquo;exemple ci-dessous montre que plusieurs bénéficiaires apparaissent plusieurs fois chacun. Le maximum que nous voyons ici est 3 doublons mais il est possible d\u0026rsquo;en avoir plusieurs dizaines pour des hôpitaux ou autres associations au nom complexe.\nLes difficultés d\u0026rsquo;exploitation persistent lorsque l\u0026rsquo;on s\u0026rsquo;intéresse à un compte bénéficiaire particulier. L\u0026rsquo;interface ne nous permet de voir qu\u0026rsquo;une liste de déclarations sans aucun moyen d\u0026rsquo;agréger les montants par exemple. Lorsque le compte bénéficie de nombreuses déclarations, il devient ingérable pour une personne sans connaissances en gestion de données d\u0026rsquo;avoir une vision globale et fiable des risques de conflit d\u0026rsquo;intérêts.\nLa qualité des données comme base de la transparence # L\u0026rsquo;association EurosForDocs # EurosForDocs a alors été créée pour résoudre ces problématiques et transformer la base Transparence Santé en un vrai outil de lutte contre les conflits d\u0026rsquo;intérêts. L\u0026rsquo;association s\u0026rsquo;organise autour de 3 objectifs principaux :\nle nettoyage des données, en particulier la fusion des doublons; la mise à disposition des données dans un tableau de bord interactif et intuitif; l\u0026rsquo;accompagnement de journalistes, chercheurs et citoyens pour l\u0026rsquo;exploitation des données. La route vers l\u0026rsquo;unification des bénéficiaires # Le besoin d\u0026rsquo;identifiants fiables # Lorsque l\u0026rsquo;on manipule des données pour lesquelles une même entité peut apparaître à plusieurs reprises, il est toujours préférable d\u0026rsquo;attribuer un numéro d\u0026rsquo;identification à chacune des identités. Ainsi, il est aisé de sélectionner que les données relatives à une entité spécifique en utilisant cet identifiant. Sur Transparence Santé, il serait pratique d\u0026rsquo;avoir un identifiant unique pour un bénéficiaire, quelles que soient les erreurs de déclaration que pourraient faire l\u0026rsquo;entreprise.\nJustement l\u0026rsquo;administration a depuis longtemps trouvé une solution à ce problème. Les professionnels de santé ayant le droit d\u0026rsquo;exercer en France doivent s\u0026rsquo;enregistrer et se voient attribuer un identifiant national : le RPPS. De même, toute entreprise ou association doit s\u0026rsquo;enregistrer et reçoit respectivement un numéro SIREN ou un numéro RNA (voire les deux).\nEn théorie les laboratoires ont toutes les informations pour créer un jeu de données propre et bien structuré. Malheureusement, les entreprises déclarantes ne les utilisent pas systématiquement. Au contraire, près de 50% des déclarations concernant des personnes morales ne déclarent pas de numéro SIREN ou RNA. Cela signifie que près de 500 millions d\u0026rsquo;euros d\u0026rsquo;influence ne peuvent pas être facilement rattachés à une institution.\nL\u0026rsquo;enjeu principal d\u0026rsquo;EurosForDocs est alors de tenter de réattribuer un de ces identifiants nationaux à chacun des bénéficiaires de la base de données.\nIndexation des bénéficiaires # Lorsque les entreprises ne déclarent pas d\u0026rsquo;identifiant national, aucun autre identifiant (même interne) n\u0026rsquo;est créé. Ainsi une entreprise peut déclarer une rémunération supplémentaire envers une entité mais en la nommant différemment. Le phénomène est amplifié si cette entité reçoit également des rémunérations d\u0026rsquo;autres entreprises. Au final, on peut avoir plusieurs mentions, potentiellement très différentes, de la même entité sans lien explicite entre elles.\nNotre stratégie de déduplication des bénéficiaires s\u0026rsquo;organise alors en deux étapes. Tout d\u0026rsquo;abord on crée un identifiant unique à chaque variante déclarée des bénéficiaires. A travers une exploration des données, nous avons décidé qu\u0026rsquo;une entreprise qui déclare deux fois les mêmes (nom, prénom, profession, code_postal) fait référence à une même entité. Nous utilisons alors une fonction de hashage qui transforme cette combinaison de caractéristiques en un entier aléatoire spécifique à cette combinaison. Cet entier va nous servir à identifier de manière unique un compte bénéficiaire. Cet article présente plus en détail les fonctions de hashage dans un autre cas d\u0026rsquo;usage.\nUne fois que nous avons défini nos comptes bénéficiaire, nous chercherons à les nettoyer puis à identifier tous les comptes qui font référence à la même entité pour, à terme, les fusionner.\nNettoyage des RPPS incohérents # Lorsque nous avons défini les informations qui définissaient un compte bénéficiaire, nous avions observé que pour une même combinaison de (nom, prénom, profession, code_postal), certaines entreprises pouvaient ajouter différents modes d\u0026rsquo;identification. Par exemple, une déclaration contiendrait le numéro RNA et une autre le numéro SIREN. Nous avons donc décidé de garder cette diversité au sein d\u0026rsquo;un compte bénéficiaire.\nIl arrive cependant régulièrement que pour des professionnels de santé, deux numéros RPPS distincts sont présents dans un même compte bénéficiaire. Après analyse détaillée de ces cas, nous en avons observé qu\u0026rsquo;un seul RPPS est cohérent avec les autres informations déclarées et que les autres numéros correspondent à des professionnels très différents.\nNotre enjeu étant de fusionner les bénéficiaires autour d\u0026rsquo;un numéro RPPS, nous devons nous assurer que chaque compte bénéficiaire est cohérent en soi. Grâce à l\u0026rsquo;annuaire des professionnels de santé, nous pouvons obtenir les informations officielles reliées à un numéro RPPS. Un système de scoring (fuzzy matching) entre les informations déclarées et les informations officielles de chaque RPPS nous permet d\u0026rsquo;estimer la cohérence entre les informations officielles et déclarées, et ne conserver que le numéro RPPS le plus pertinent.\nAttribution du RPPS # De nombreuses déclarations n\u0026rsquo;ont pas le luxe d\u0026rsquo;avoir même un seul numéro RPPS. Nous cherchons alors à relier les informations documentées par l\u0026rsquo;entreprise avec un.e professionnel.le de santé de l\u0026rsquo;annuaire. Nous cherchons d\u0026rsquo;abord à trouver une correspondance exacte sur le nom, prénom, profession et code postal. Nous ajoutons à cette logique des mécanismes pour traiter le cas de noms composés pour lesquels seule une partie peut être renseignée, ou l\u0026rsquo;ordre inversé.\nDe nombreuses déclarations ont des informations manquantes ou erronnées, ce qui rend la première étape inefficace pour retrouver un RPPS. Nous testons alors les comptes bénéficiaires non identifiés avec des contraintes plus souples, par exemple ne pas considérer le code postal. Avec un relâchement des contraintes, le risque de tomber sur des homonymes augmente. Nous n\u0026rsquo;attribuons alors un RPPS que s\u0026rsquo;il n\u0026rsquo;y a qu\u0026rsquo;un seul professionnel de santé correspondant aux contraintes.\nAttribuer des liens directs # Une fois que nous avons attribué un maximum d\u0026rsquo;identifiants RPPS aux bénéficiaires, nous allons chercher à identifier directement des liens entre des comptes. On espère ainsi que les comptes sans RPPS puissent en obtenir un de manière indirecte. De même on espère que les comptes de personnes morales, pour lesquels nous n\u0026rsquo;avons pas de mécanisme pour retrouver le SIREN, puissent en obtenir un.\nDe manière similaire à la création des comptes de bénéficiaires, nous regroupons les comptes par (nom, prénom, code postal et profession). Si le groupe regroupe plusieurs numéros SIREN (ou RNA ou RPPS) distincts, nous considérons que ces informations font référence à plusieurs entités distinctes (potentiellement à cause d\u0026rsquo;erreurs de déclarations) et ne faisons rien. Dans le cas contraire, nous créons un lien entre tous ces comptes pour les considérer comme appartenant à la même entité. Relier les association par machine learning # Contrairement aux professionnels de santé pour lesquels il y a relativement peu de variations possibles (à part le sujet de noms composés), les associations (ou personnes morales en général) peuvent être nommées de manière très différente tout en maintenant la clarté de l\u0026rsquo;entité ciblée. Ce cas d\u0026rsquo;étude Euros For Docs explore un cas particulier.\nNous cherchons donc à identifier si deux noms potentiellement très différents (du point de vue des similarités standard entre chaînes de caractères) font référence à la même entité. Pour obtenir des éléments à comparer entre les deux noms, nous appliquons une méthode appelée shingles. L\u0026rsquo;idée est de découper notre nom d\u0026rsquo;association en toutes les combinaisons de 3 lettres consécutives. Le nom d\u0026rsquo;association est alors transformé en une phrase dont les éléments ne sont pas des mots mais nos trigrammes. À partir de cette nouvelle représentation de chaque nom, nous pouvons appliquer des techniques de langage naturel (NLP) standard pour évaluer la similarité entre les deux noms. Enfin, un modèle de machine learning va utiliser les différentes notions de similarité et déterminer la meilleure manière de les combiner pour identifier les paires de noms d\u0026rsquo;une même entité.\nFusion des comptes # À ce niveau du traitement des données, les comptes bénéficiaires peuvent être reliés à un ou plusieurs identifiants nationaux mais également à un ou plusieurs autres comptes. Pour recréer une entité bénéficiaire, nous représentons l\u0026rsquo;ensemble des comptes et des relations sous forme de graphe. Cette représentation nous permet d\u0026rsquo;utiliser un algorithme pour regrouper tous les comptes bénéficiaires reliés les uns aux autres même de manière indirecte. Chacun de ces blobs est alors interprété comme une entité. Les comptes appartenant à l\u0026rsquo;entité seront fusionnés et les informations agrégées de l\u0026rsquo;entité serviront à normaliser les informations bénéficiaires dans les déclarations. Pour plus de détails sur la fusion des comptes, voir cet article dédié\nToujours pour des raisons de qualité de données, il peut arriver que plusieurs SIREN (ou RPPS, RNA) soient présents dans un même blob. Un identifiant national devant identifier de manière unique une entité, cette situation nous informe qu\u0026rsquo;un ou plusieurs liens dans notre base sont faux et regroupent deux comptes correspondant à des entités séparées. Nous sommes capables de facilement identifier ces situations (à défaut de pouvoir les corriger) et nous empêchons la fusion des comptes appartenant à ces blobs. C\u0026rsquo;est pour cette raison qu\u0026rsquo;en pratique, les comptes bénéficiaires des CHU sont rarement fusionnés car il y a toujours une déclaration pour introduire un mauvais SIREN ou le RNA d\u0026rsquo;une association.\nSans qualité des données, la transparence est un mythe # Ce travail de nettoyage d\u0026rsquo;EurosForDocs améliore sensiblement la qualité des données Transparence Santé. La capacité à identifier de manière unique et précise un professionnel de santé (et bientôt une association) facilite énormément le travail des journalistes et citoyens, en témoignent les nombreuses collaborations dans l\u0026rsquo;écriture d\u0026rsquo;articles.\n","date":"10 janvier 2026","externalUrl":null,"permalink":"/conferences/2026-02-11-aperops-eurosfordocs/","section":"Conférences","summary":"Présentation effectuée dans le cadre du meetup Bordeaux ApérOps le 11 février 2026.\nTélécharger les slides (PDF)\nL’enjeu de la transparence dans la santé # Le scandale du Mediator # Le Mediator est un médicament dérivé de l’amphétamine, commercialisé par le laboratoire Servier comme antidiabétique à partir de 1976. Au-delà de son cadre officiel d’utilisation, il a toutefois été massivement prescrit comme coupe-faim pendant plus de trente ans. Durant toutes ces années, il aurait entraîné la mort de plus de 1500 personnes et créé de graves pathologies à des milliers d’autres.\n","title":"EurosForDocs : Renforcer la transparence dans la santé grâce à la data quality","type":"conferences"},{"content":"","date":"16 décembre 2025","externalUrl":null,"permalink":"/tags/data-engineering/","section":"Tags","summary":"","title":"Data Engineering","type":"tags"},{"content":"En tant que data engineer, nous ne sommes pas toujours maîtres de nos données sources. En particulier lorsque l\u0026rsquo;on utilise des données ouvertes, nous sommes à la merci des changements des producteurs de données.\nDans le cadre du projet Euros For Docs, notre source principale de données est la base Transparence Santé. Ce fichier publié chaque jour contient plus de 8 millions de déclarations de rémunérations de professionnels de santé ou d\u0026rsquo;associations de santé par des laboratoires pharmaceutiques. D\u0026rsquo;un jour à l\u0026rsquo;autre, le fichier subit de nombreuses modifications : de nouvelles déclarations sont ajoutées, certaines disparaissent et d\u0026rsquo;autres sont simplement modifiées.\nDes fichiers qui changent quotidiennement # Dans une optique de suivi des évolutions des déclarations, nous voulons créer un fichier d\u0026rsquo;historique contenant toutes les versions des déclarations. Grâce à un identifiant unique de chaque déclaration fourni dans le fichier, nous sommes capables chaque jour de comparer une déclaration avec sa dernière valeur historique et d\u0026rsquo;identifier les changements dans les données sources.\nConsidérons alors la table suivante comme les dernières valeurs observées des déclarations.\nid montant beneficiaire date date_modif date_delete 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 Considérons maintenant que le fichier du jour contient les déclarations suivantes.\nid montant beneficiaire date_declaration 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 Ce nouveau fichier propose 4 situations différentes.\nLa déclaration 1 apparaît dans le fichier du jour avec exactement les mêmes informations que dans le fichier d\u0026rsquo;historique. Puisque rien n\u0026rsquo;a changé dans cette déclaration, on ne souhaite rien faire concernant celle-ci dans le fichier d\u0026rsquo;historique. La déclaration 2 existait déjà dans le fichier d\u0026rsquo;historique mais la version du jour a deux modifications : le montant est passé de 200 à 220 et une typo a été corrigée sur le bénéficiaire (ajout d\u0026rsquo;un S à la fin). Nous souhaitons garder trace de cette modification et ajouter cette version de la déclaration dans l\u0026rsquo;historique, avec la date de modification du jour. La déclaration 3 n\u0026rsquo;apparaît plus dans le fichier du jour alors qu\u0026rsquo;elle existait dans l\u0026rsquo;historique. Nous voulons alors documenter dans le fichier d\u0026rsquo;historique la date de disparition de cette déclaration. La déclaration 4 est une nouvelle déclaration qui n\u0026rsquo;était jamais apparue dans le fichier avant cette version. Nous voulons alors l\u0026rsquo;ajouter dans le fichier d\u0026rsquo;historique. La déclaration 5 n\u0026rsquo;est pas dans le fichier du jour mais le fichier d\u0026rsquo;historique mentionne que la déclaration avait déjà disparu dans des versions antérieures du fichier. Nous n\u0026rsquo;attendons donc aucun traitement sur cette déclaration. Le cas simple des ajouts et suppressions # L\u0026rsquo;apparition de nouvelles déclarations et la disparition d\u0026rsquo;anciennes sont le cas le plus simple à traiter. Puisque les fichiers nous proposent un id unique pour les déclarations, nous pouvons nous contenter de comparer la liste des ID du fichier d\u0026rsquo;historique avec celle du fichier du jour. Cette procédure est très simple à mettre en place en SQL et très rapide.\nPar exemple, on peut préparer les nouvelles déclarations à injecter dans le fichier avec cette simple requête SQL.\nselect declarations.*, current_date() as date_modif, cast(null as date) as date_delete from declarations left join historical_declarations hist using (id) where hist.id is null Ce qui nous donne la déclaration 4 à injecter.\nid montant beneficiaire date date_modif date_delete 4 400 ORDRE DES DIETETICIENS 2025-12-04 2025-12-08 NaT Et enfin, on peut identifier la disparition de la déclaration 3 avec la requête suivante.\nselect hist.id from historical_declarations hist left join declarations using (id) where hist.date_delete is null and declarations.id is null Une détection lourde des modifications # La gestion des déclarations modifiées est bien plus complexe. Le fichier de déclarations contient en réalité une cinquantaine de colonnes que les laboratoires peuvent modifier à volonté. Pour identifier les déclarations modifiées depuis la dernière version du fichier, nous devons créer une condition SQL qui contienne la comparaison des cinquante colonnes une à une pour trouver toutes les déclarations qui étaient déjà présentes dans le fichier de la veille mais dont au moins une valeur a été modifiée. En continuant l\u0026rsquo;exemple commencé plus tôt, la requête prend la forme suivante.\nwith modified as ( select dec.* from declarations dec join historical_declarations h using (id) where h.date_delete is null and not ( coalesce(h.montant, -1) = coalesce(dec.montant, -1) and coalesce(h.beneficiaire, \u0026#39;__NULL__\u0026#39;) = coalesce(dec.beneficiaire, \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 date_modif, cast(null as date) as date_delete from modified Ce qui donne la table suivante à injecter dans notre fichier d\u0026rsquo;historique.\nid montant beneficiaire date date_modif date_delete 2 220 FEDERATION DES INFIRMIERS 2025-12-02 2025-12-08 NaT Cette stratégie pose deux limitations.\nLa requête elle-même peut rapidement devenir illisible avec 50 conditions (au lieu de 3) à prendre en compte. En vérité, les outils modernes permettent de contourner cette limitation avec le templating. Chez EurosForDocs, c\u0026rsquo;est du code Python qui organise les appels successifs en SQL. Nous pouvons alors créer dynamiquement la requête grâce à une simple boucle for sur les variables de la déclaration.\nLa deuxième problématique de notre stratégie est la performance. Pour vérifier que deux versions d\u0026rsquo;une déclaration sont identiques, il faut calculer 50 conditions. Parmi ces conditions, certaines peuvent être particulièrement intenses, telles que la comparaison entre deux longues chaînes de caractères. Ces limitations à l\u0026rsquo;échelle de plusieurs millions de lignes et de 50 colonnes peuvent rapidement devenir la source principale de lenteur d\u0026rsquo;un pipeline de données.\nFonctions de hash # Une autre solution plus performante se base sur la notion de fonction de hash. Une fonction de hash transforme un texte arbitraire en une signature (numérique ou alphanumérique). Cette signature est caractéristique du texte initial dans le sens où appliquer plusieurs fois la fonction de hash sur le même texte donnera toujours la même signature. Par contre deux textes qui diffèrent, même par une seule typographie, obtiendront des signatures radicalement différentes.\nPrenons un cas simple : les numéros de sécurité sociale français. La plupart des numéros sont une combinaison de nombres liés à notre date et lieu de naissance. Les deux derniers chiffres sont par contre beaucoup moins connus : ils sont justement utilisés dans le cadre d\u0026rsquo;une fonction de hash basique.\nL\u0026rsquo;algorithme de Luhn est une manière de combiner les chiffres d\u0026rsquo;un numéro pour obtenir un entier comme signature. L\u0026rsquo;image ci-dessous montre comment calculer cette signature pour une combinaison de chiffres arbitraire.\nEn général, l\u0026rsquo;algorithme de Luhn ne se limite pas à calculer cette signature. Dans le cas du numéro de sécurité sociale, les deux derniers numéros sont ajoutés et choisis spécifiquement pour forcer la signature à être un multiple de 10. Ainsi, si nous rencontrons un numéro avec une signature qui n\u0026rsquo;est pas un multiple de 10, nous pouvons être sûrs que ce numéro contient au moins une erreur. Il est possible d\u0026rsquo;utiliser cette propriété pour vérifier que le chiffre fourni dans un formulaire n\u0026rsquo;est pas invalide sans avoir à demander à l\u0026rsquo;assurance maladie la liste de tous les numéros valides.\nLimitations des hash # Une des limitations évidentes des fonctions de hash est qu\u0026rsquo;il existe bien moins de signatures uniques que de textes possibles. Dans le cas des numéros de sécurité sociale, seules 10 signatures sont possibles, dont une seule (le 0) a vraiment un sens. La plupart des systèmes informatiques encodent aujourd\u0026rsquo;hui les entiers sur 64 bits : ce qui représente 2**64=18 446 744 073 709 551 616 signatures uniques. Même si ce chiffre est énorme, il est insignifiant par rapport à l\u0026rsquo;ensemble de tous les textes (et leurs sous-parties) qui peuvent exister. De nombreux textes vont donc partager la même signature.\nLe résultat d\u0026rsquo;une fonction de hash peut sembler aléatoire et deux textes très similaires peuvent obtenir des nombres radicalement différents. Cela entraîne que la probabilité que deux textes différents partagent la même signature est d\u0026rsquo;autant plus faible que le nombre de signatures disponibles est grand. Ainsi, on peut toujours choisir une fonction de hash avec suffisamment de signatures disponibles pour considérer nulle la probabilité que deux textes différents de notre jeu de données partagent la même signature.\nDétection des modifications grâce au hash # EurosForDocs utilise alors une fonction de hash pour identifier les déclarations modifiées entre deux versions de notre fichier source. Pour chaque déclaration passée ou présente, les 50 colonnes du fichier sont concaténées pour créer un gros texte. On peut ensuite faire passer ce texte dans une fonction de hash pour obtenir une signature de cette version de la déclaration. L\u0026rsquo;identification des modifications est alors très rapide et très simple à implémenter : on regarde pour chaque déclaration si la valeur actuelle de la signature correspond à celle de la veille.\nid montant beneficiaire date date_modif date_delete 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 Nous pouvons ensuite directement calculer ce hash sur les nouvelles déclarations et comparer avec le hash historique pour identifier les déclarations modifiées.\nWITH declas_with_hash AS ( SELECT *, HASH( CONCAT( COALESCE(beneficiaire, \u0026#39;__NULL__\u0026#39;), COALESCE(montant::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 Cette méthode permet d\u0026rsquo;obtenir des gains de performances. Chaque jour, nous devons uniquement comparer deux entiers pour chaque déclaration au lieu d\u0026rsquo;une cinquantaine de colonnes : ce qui consomme beaucoup moins de mémoire (pas besoin de lire les chaînes de caractères) et est beaucoup plus rapide.\nConclusion # Les fonctions de hash offrent une alternative efficace pour détecter les modifications dans des jeux de données volumineux et fréquemment mis à jour. En transformant des ensembles de colonnes complexes en signatures numériques simples, elles permettent de simplifier significativement les requêtes SQL et d\u0026rsquo;améliorer les performances des pipelines de données.\nDans le cas d\u0026rsquo;EurosForDocs, cette approche a permis de réduire la complexité de la détection des modifications de plusieurs dizaines de conditions SQL à une simple comparaison d\u0026rsquo;entiers. Les gains en termes de temps d\u0026rsquo;exécution et de consommation mémoire sont particulièrement notables lorsque l\u0026rsquo;on traite des millions de lignes quotidiennement et que l\u0026rsquo;on doit se contenter de machines avec peu de mémoire.\nCette technique s\u0026rsquo;applique à de nombreux autres cas d\u0026rsquo;usage en data engineering : suivi de versions de fichiers, détection de doublons, validation d\u0026rsquo;intégrité de données, ou encore déduplication. Il est important de choisir une fonction de hash adaptée à la taille de votre jeu de données pour minimiser les risques de collisions, même si ceux-ci restent négligeables dans la plupart des contextes pratiques.\n","date":"16 décembre 2025","externalUrl":null,"permalink":"/articles/unicity_sha/","section":"Articles","summary":"En tant que data engineer, nous ne sommes pas toujours maîtres de nos données sources. En particulier lorsque l’on utilise des données ouvertes, nous sommes à la merci des changements des producteurs de données.\n","title":"Les fonctions de hash pour simplifier la création d'historiques","type":"articles"},{"content":"","date":"16 décembre 2025","externalUrl":null,"permalink":"/tags/sql/","section":"Tags","summary":"","title":"Sql","type":"tags"},{"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":"1 novembre 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":" Le défi de l\u0026rsquo;identification des bénéficiaires # L\u0026rsquo;écosystème de la santé rassemble plusieurs types d\u0026rsquo;acteurs : laboratoires pharmaceutiques, professionnels de santé et associations de patients. Ces acteurs entretiennent entre eux des relations financières et d\u0026rsquo;influence qui peuvent créer des conflits d\u0026rsquo;intérêt.\nPour limiter ces risques, la base Transparence Santé impose aux entreprises de la santé de déclarer publiquement les avantages et rémunérations qu\u0026rsquo;elles versent aux professionnels de santé et aux autres acteurs du secteur. Cette base de données est utilisée par le projet EurosForDocs pour analyser ces flux financiers.\nMais pour analyser précisément ces liens d\u0026rsquo;intérêt, il faut pouvoir identifier sans ambiguïté chaque bénéficiaire d\u0026rsquo;avantages ou de rémunérations. Or, la plateforme gouvernementale accorde une grande liberté aux entreprises dans la rédaction de leurs déclarations. Cette flexibilité conduit à un problème pratique : un même bénéficiaire peut être décrit de nombreuses façons différentes selon les entreprises. Il peut alors être compliqué de regrouper toutes les déclaration le concernant.\nLa situation idéale pour regrouper les différentes déclarations relatives à un même bénéficiaire serait la présence d\u0026rsquo;un identifiant national unique. Les professionnels de santé disposent justement d\u0026rsquo;un tel numéro : le numéro RPPS. Un ancien référentiel (le numéro ADELI) est également disponible et peut être traduit en RPPS pour la plupart des professions. Les sociétés savantes et les associations de patients peuvent être identifiées par leur numéro national d\u0026rsquo;association (RNA) ou leur numéro SIREN.\nEn pratique, les déclarations sont loin de respecter les standards de qualité attendus. Le taux de saisie d\u0026rsquo;un numéro SIREN ou RNA pour les personnes morales n\u0026rsquo;est que de 50%. La situation était similaire pour les professionnels de santé, mais une mise à jour de la plateforme de déclaration a permis d\u0026rsquo;augmenter le taux de déclaration à 90%.\nUn des objectifs du retraitement d\u0026rsquo;EurosForDocs est de fusionner tous les comptes de bénéficiaires relatifs à une même entité physique, même en l\u0026rsquo;absence d\u0026rsquo;identifiant national. Pour cela, nous avons implémenté un système en quatre étapes :\nCorrection des identifiants incohérents. Nous corrigeons les déclarations qui ont des numéros RPPS mais pour lesquelles les noms, prénoms et profession déclarés sont incohérents par rapport aux informations de l\u0026rsquo;annuaire officiel RPPS. Cette étape est le sujet d\u0026rsquo;un article dédié.\nAttribution d\u0026rsquo;identifiants. Nous tentons de retrouver l\u0026rsquo;identifiant manquant d\u0026rsquo;un bénéficiaire en le recherchant dans un annuaire officiel (RPPS pour les professionnels de santé, SIREN/RNA pour les personnes morales).\nRecherche de liens directs. Lorsque l\u0026rsquo;identification dans un annuaire échoue, nous cherchons des correspondances directes entre comptes en comparant leurs informations (nom, prénom, profession, etc.).\nCréation d\u0026rsquo;entités. Un algorithme regroupe automatiquement tous les comptes qui sont reliés entre eux, directement ou par l\u0026rsquo;intermédiaire d\u0026rsquo;autres comptes pour recréer les entités physiques auxquelles ils correspondent.\nMéthodes de rapprochement des comptes # Comme mentionné dans la section précédente, la situation idéale consiste à avoir un identifiant national pour chaque compte bénéficiaire. Lorsque aucun n\u0026rsquo;est présent, nous cherchons à en retrouver grâce à différentes sources de vérité.\nRéattribution des identifiants # Les professionnels de santé constituent les cas les plus simples à traiter. L\u0026rsquo;annuaire santé (ou RPPS) liste tous les professionnels de santé exerçant en France, parfois avec différentes variantes pour leur nom, prénom ou code postal. Il inclut également pour chaque professionnel son numéro RPPS et/ou ADELI. Nous pouvons ainsi tenter d\u0026rsquo;attribuer directement un numéro RPPS aux professionnels déclarés sans aucun identifiant.\nPour chacun de ces professionnels, nous recherchons dans l\u0026rsquo;annuaire une personne avec le même nom, prénom et profession. S\u0026rsquo;il n\u0026rsquo;existe qu\u0026rsquo;un seul numéro RPPS dans l\u0026rsquo;annuaire avec ces informations (donc pas d\u0026rsquo;homonymes qui pourraient créer une ambiguïté), nous l\u0026rsquo;attribuons à ce compte.\nPlusieurs variantes de cette logique sont testées pour ajuster les seuils de tolérance sur les informations considérées et tenter de contourner les problématiques d\u0026rsquo;homonymie. Par exemple, on peut tenter de jouer sur le code postal s\u0026rsquo;il est déclaré pour lever des ambiguités, ou travailler sur les sous parties d\u0026rsquo;un nom composé. Contrairement aux techniques appliquées dans cet article, on n\u0026rsquo;attribue pas un numéro RPPS à un compte si nous n\u0026rsquo;obtenons pas un matching exact pour une approche donnée. Nous choisissons donc de ne pas pouvoir traiter de simples erreurs typographiques, qui ouvriraient la porte à beaucoup trop de faux positifs. Parmis les 2 millions de comptes de professionnels déclarés sans RPPS, 60% se voient attribuer un identifiant à la fin de cette procédure.\nEn théorie, nous devrions pouvoir appliquer la même logique aux personnes morales grâce aux annuaires des associations et SIREN. Malheureusement, la seule information réellement utilisable est le nom de l\u0026rsquo;entité. Alors qu\u0026rsquo;on s\u0026rsquo;attend à trouver le nom exact pour une personne physique (avec parfois des problématiques de nom de jeune fille/d\u0026rsquo;épouse), un nom d\u0026rsquo;association permet de plus grandes variations sans remettre en question l\u0026rsquo;intelligibilité de la déclaration. Par exemple, dans cette étude de cas, l\u0026rsquo;Association Clinique et Thérapeutique Infantile du Val de Marne a été identifiée sous différentes mentions, allant du nom complet jusqu\u0026rsquo;à l\u0026rsquo;acronyme ACTIV en passant par des versions condensées telles que \u0026ldquo;Ass Cliniq Therap Infantil\u0026rdquo;. Une telle diversité ne permet pas d\u0026rsquo;appliquer une logique d\u0026rsquo;attribution similaire à celle des personnes physiques.\nLors de l\u0026rsquo;exploration des données, nous avons également identifié des cas particuliers. Certaines entreprises déclarent des numéros d\u0026rsquo;identification qui ne semblent pas correspondre à des référentiels nationaux, mais qui semblent être liés de manière unique à un même bénéficiaire. Nous en avons déduit que ces numéros doivent être des numéros d\u0026rsquo;identification internes. Nous utilisons alors ces numéros (par entreprise) comme des identifiants nationaux pour lier entre eux différents comptes d\u0026rsquo;une même entité.\nEnfin, certains doublons de comptes résistent à toutes nos méthodes (incluant celles non encore présentées). Ces doublons sont en général identifiés par des utilisateurs durant leur explorations de certaines personnes ou associations spécifiques. Nous avons alors mis en place un système de modifications manuelles qui permet d\u0026rsquo;atttribuer des identifiants à des comptes bénéficiaires.\nLien direct entre comptes # Une deuxième stratégie pour fusionner des comptes consiste à prouver que deux comptes bénéficiaires font référence à la même entité, même en l\u0026rsquo;absence d\u0026rsquo;identifiant. Dans le cas idéal, le premier compte possède un identifiant qui sera propagé au second. Lorsque aucun compte n\u0026rsquo;a d\u0026rsquo;identifiant, ce lien permet néanmoins de fusionner les deux comptes, en espérant qu\u0026rsquo;un autre lien direct avec un troisième compte permettra une identification ultérieure.\nProfessionnels de santé # La première stratégie mise en place s\u0026rsquo;applique aux professionnels de santé. Nous cherchons à regrouper les comptes bénéficiaires qui ont le même nom, prénom, profession et code postal, mais qui peuvent être déclarés par des entreprises différentes.\nCette approche peut néanmoins produire de faux positifs, même avec l\u0026rsquo;exigence d\u0026rsquo;un code postal renseigné. Imaginons par exemple un cas où un compte sans RPPS coexiste avec deux autres comptes partageant les mêmes nom, prénom, profession et code postal, mais possédant des RPPS distincts. Dans cette situation, l\u0026rsquo;attribution du bon RPPS devient impossible. Après avoir complété les RPPS dans la mesure du possible lors des étapes précédentes, nous appliquons une contrainte supplémentaire : chaque groupe de comptes homonymes ne peut contenir qu\u0026rsquo;un seul numéro RPPS. Cette limitation réduit significativement les risques d\u0026rsquo;erreur d\u0026rsquo;attribution.\nPersonnes morales # Concernant les personnes morales, la stratégie est similaire mais ne peut se baser que sur le nom de l\u0026rsquo;entité. Ici, le risque de fusionner des comptes homonymes est beaucoup plus élevé : il n\u0026rsquo;est pas rare que des entités différentes aient le même acronyme et que les entreprises ne déclarent que ce derner. Nous avons également identifié un nombre conséquent de déclarations pour lesquelles le nom du bénéficiaire est un mot-clé non indicatif: \u0026ldquo;Hôpital\u0026rdquo; par exemple.\nCes différents cas rendent important d\u0026rsquo;avoir un mécanisme de limitation des faux positifs. Comme pour les professionnels de santé, nous imposons à un groupe de bénéficiaires homonymes de ne pas avoir plus d\u0026rsquo;un seul identifiant parmi eux pour permettre aux comptes sans identifiants d\u0026rsquo;en recevoir un. De plus nous interdisons les liens entre les comptes dont les noms sont des mots non indicatifs.\nLiens manuels # Enfin, certaines études particulières effectuées par nos utilisateurs nous ont remonté des liens entre des comptes pour lesquels aucun identifiant n\u0026rsquo;est renseigné. La plupart du temps, nous essayons de leur attribuer manuellement des identifiants comme mentionné dans la section précédente.\nMalheureusement, il peut être difficile d\u0026rsquo;obtenir un identifiant pour certaines entités. Par exemple, certains groupes de travail inter-entités n\u0026rsquo;ont techniquement pas d\u0026rsquo;existence légale mais reçoivent des financements pour leur activité. Même si ces financements sont sûrement attribués comptablement à des entités légales qui participent à ces groupes de travail, la déclaration ne mentionne que le groupe, qui n\u0026rsquo;aura alors pas d\u0026rsquo;identifiant. Dans ces cas particuliers, nous créons alors une nouvelle base de données de liens entre comptes qui permet de lier des comptes deux à deux.\nCréation des entités # La section précédente nous a présenté plusieurs cas de figure de liens entre les comptes. Selon la qualité des déclarations, ces liens peuvent être nombreux et divers. Nous avons donc besoin d\u0026rsquo;une stratégie pour reconstituer des entités uniques et de qualité à partir de cet ensemble de comptes déclarés et des liens entre eux.\nRegroupement par identifiant # Considérons le cas le plus simple où plusieurs comptes sont reliés entre eux via un même identifiant. Nous pouvons alors regrouper tous les comptes avec le même identifiant. Par exemple, imaginons que les comptes suivants sont tous reliés au même numéro RPPS :\nid nom prenom profession rpps 1 Dupont Christine pharmacien 1000 2 Dupont Christine 1000 3 Dupont Cristine 1000 Nous cherchons à créer une entité pour cette pharmacienne qui soit la meilleure combinaison possible des informations contenues dans tous les comptes. Ici, le nom ne pose aucun problème puisqu\u0026rsquo;il est identique partout. Le nom final de notre entité sera donc Dupont.\nNotre stratégie de déduplication nous permet d\u0026rsquo;enrichir nos données avec la profession de cette personne. En effet, les déclarations correspondant aux comptes bénéficiaires 2 et 3 n\u0026rsquo;ont pas documenté de profession. Grâce à la mise en relation de ces 3 comptes grâce au numéro RPPS, nous pouvons attribuer une profession à l\u0026rsquo;ensemble des comptes, ce qui améliorera la qualité des déclarations sans cette information.\nCe système nous permet également d\u0026rsquo;unifier certaines informations variables. Par exemple, le compte numéro 3 a une typo sur le prénom : le h est manquant. Il pourrait tout aussi bien renseigner une variante du prénom : nous avons des cas de Marie-Christine simplement déclarés comme Marie ou Christine. Il y a donc naturellement une variabilité dans les données déclarées. Nous pouvons choisir la variante la plus pertinente pour créer notre entité finale. Ainsi, toutes les déclarations avec des informations erronnées et/ou variantes pourront être modifiées pour harmoniser toutes les déclarations liées à cette personne.\nPour permettre de relier un compte bénéficiaire à une entité, il est préférable de créer un ID pour cette entité. Il est important d\u0026rsquo;avoir un identifiant qui possède une certaine stabilité. En effet, nous avons quotidiennement de nouvelles déclarations ou des modifications. Nous souhaitons un identifiant qui ne change que peu lorsque de nouvelles déclarations sont créés, pour que les utilisateurs puissent facilement retrouver les bénéficiaires qui les intéressent d\u0026rsquo;un jour à l\u0026rsquo;autre.\nLa solution que nous avons choisie est d\u0026rsquo;utiliser le plus petit ID présent parmi les comptes dupliqués. L\u0026rsquo;ajout de nouveaux comptes à la liste des dupliqués ne changera pas l\u0026rsquo;ID de référence pour le groupe. La mise à jour de déclarations ou l\u0026rsquo;amélioration de la logique de fusion peuvent changer l\u0026rsquo;ID, mais la proportion de comptes impactés sera relativement faible.\nImpact des relations variées # La logique de regroupement par identifiant unique devient plus complexe lorsque plusieurs types de liens coexistent entre les comptes.\nConsidérons l\u0026rsquo;exemple suivant : les comptes 0 et 1 partagent le même numéro RPPS, le compte 2 est lié au compte 1 via un identifiant interne d\u0026rsquo;entreprise, et le compte 3 est directement relié au compte 1 par une correspondance de données.\nSi nous nous limitons au regroupement par RPPS (encadré rouge), nous exclurions les comptes 2 et 3 de l\u0026rsquo;entité finale, alors qu\u0026rsquo;ils correspondent au même bénéficiaire. La solution consiste à étendre le regroupement de manière récursive : tous les comptes liés à un membre du groupe initial doivent être inclus dans l\u0026rsquo;entité finale. Cette logique s\u0026rsquo;applique de manière itérative jusqu\u0026rsquo;à ce qu\u0026rsquo;aucun nouveau compte ne puisse être ajouté.\nUne fois tous les comptes liés identifiés, nous appliquons la même stratégie de déduplication que précédemment pour déterminer le nom, prénom et autres caractéristiques finales de l\u0026rsquo;entité.\nRegroupement des sous composants # Cette logique itérative de devoir chercher de nouveaux comptes liés à un membre d\u0026rsquo;un groupe à travers différents types de liens est assez complexe à mettre en place lorsque l\u0026rsquo;on se place dans le contexte de données ayant la forme d\u0026rsquo;un tableau Excel; ce que nous avons fait implicitement dans cet article ainsi que les précédents parlant d\u0026rsquo;EurosForDocs. Cependant, un changement de paradigme va nous permettre d\u0026rsquo;implémenter cette logique de manière extrêmement simple. Ce paradigme est la représentation des données sous la forme d\u0026rsquo;un réseau.\nUn réseau se compose d\u0026rsquo;une liste d\u0026rsquo;entités (des nœuds) qui peuvent être reliées entre elles à travers différents mécanismes. La notion de réseau est assez connue aujourd\u0026rsquo;hui à travers les réseaux sociaux, où des personnes sont reliées entre elles par des liens \u0026ldquo;d\u0026rsquo;amitié\u0026rdquo; sur Facebook ou des utilisateurs reliés à des produits et entreprises dans une base de données d\u0026rsquo;e-commerce par exemple.\nPour créer notre réseau de doublons, nous devons nous poser deux questions principales : en quoi consisteront les nœuds du réseau et quels seront les liens entre eux. Premièrement, notre réseau va contenir tous les comptes bénéficiaires comme nœuds. Cependant, nous allons aussi ajouter comme nœuds tous les identifiants présents dans la base. Nous aurons donc un ensemble de nœuds correspondant à différents SIREN, un autre ensemble pour les numéros RPPS, etc\u0026hellip; Les identifiants internes des entreprises que nous avions mentionnés plus tôt généreront également des nœuds.\nEnsuite nous allons chercher à relier ces nœuds entre eux. Toutes les règles métier détaillées plut haut vont nous permettre de lier des nœuds entre eux. La présence d\u0026rsquo;un numéro RPPS déclaré (ou retrouvé) permet de relier le nœud correspondant à ce bénéficiaire avec le nœud correspondant à son numéro RPPS. Les relations directes entre les comptes peuvent également être représentées par des liens entre leurs nœuds respectifs. C\u0026rsquo;est cette représentation qui a été utilisée dans l\u0026rsquo;exemple précédent. Une fois ce réseau créé nous obtenons quelque chose qui va ressembler à l\u0026rsquo;image suivante, mais avec près de 8 millions de nœuds et 8 millions de liens entre ces neouds.\nSi on regarde attentivement le réseau, on se rend compte que les nœuds sont naturellement organisés en 4 groupes. Dans chacun de ces groupes, les bénéficiaires sont reliés entre eux soit directement, soit à travers une liaison en commun avec un numéro d\u0026rsquo;identification. Le groupe en bas à gauche montre bien que la plupart des noeuds s\u0026rsquo;organisent autours d\u0026rsquo;un numéro SIREN et d\u0026rsquo;un numéro RNA, mais avec des noeuds à gauche regroupés autour du noeud 37, lui même lié au reste du group via des relations directes avec d\u0026rsquo;autres comptes bénéficiaires. Chacun de ces groupes correspond alors à l\u0026rsquo;ensemble des noeuds reliés entre eux de près ou de loin; c\u0026rsquo;est à dire à une entité finale.\nLes réseaux en tant qu\u0026rsquo;objets mathématiques possèdent une vaste gamme d\u0026rsquo;algorithmes qui permettent de les explorer et d\u0026rsquo;en déduire leurs propriétés. En particulier, l\u0026rsquo;algorithme des composants connectés va explorer un réseau et répartir des nœuds dans des groupes de manière à ce qu\u0026rsquo;il soit toujours possible d\u0026rsquo;atteindre un nœud du groupe depuis un autre, éventuellement en passant par d\u0026rsquo;autres nœuds intermédiaires, en suivant les liens. Par contre, deux nœuds n\u0026rsquo;appartenant pas au même groupe ne seront pas accessibles l\u0026rsquo;un de l\u0026rsquo;autre.\nCe nouveau formalisme est alors utilisé pour extraire les groupes de comptes bénéficiaires qui permettront de créer les entités. Puisque le problème des composants connectés est relativement ancien, nous avons accès à des implémentations optimisées pour des données de type graphe. Cela rend la procédure beaucoup plus efficace qu\u0026rsquo;un code manuel; potentiellement dans un formalisme et une technologie non prévus pour ce genre de problème. Le fait de pouvoir appeler un algorithme très connu réduit aussi la quantité de code (puisque l\u0026rsquo;on peut appeler un outil dédié) et facilite la documentation. Au final, nous avions 7.1 millions de comptes bénéficiaires que nous avons pu dédupliquer en 2.1 millions d\u0026rsquo;entités.\nGestion des incohérences # L\u0026rsquo;algorithme des composants connectés révèle un problème important : certains groupes contiennent plusieurs identifiants du même type (plusieurs RPPS ou plusieurs SIREN). Cette situation indique une erreur dans les données, car chaque identifiant devrait être unique pour une entité.\nDans l\u0026rsquo;exemple illustré, le groupe du bas contient deux numéros RPPS distincts (77 et 75), suggérant que deux entités différentes ont été incorrectement liées. Le compte bénéficiaire 2 présente probablement un lien erroné. Des situations plus complexes existent, comme le groupe de gauche où les nœuds SIREN se trouvent en périphérie de la structure.\nLa création d\u0026rsquo;entité grâce aux composants connectés présente deux avantages. Elle permet de regrouper efficacement les comptes liés tout en identifiant automatiquement les groupes présentant des incohérences. Pour limiter les erreurs de traitement, nous choisissons de ne pas fusionner les comptes appartenant à un groupe incohérent, mais de les marquer pour un traitement ultérieur, automatique ou manuel.\nConclusion # La déduplication de comptes bénéficiaires de la base Transparence Santé nécessite une approche progressive combinant attribution d\u0026rsquo;identifiants, correspondances directes et regroupement algorithmique. La modélisation en graphe transforme ce problème complexe en un algorithme standard de composants connectés, permettant de traiter efficacement 7,1 millions de comptes pour obtenir 2,1 millions d\u0026rsquo;entités distinctes.\nCette méthodologie offre un cadre structuré pour l\u0026rsquo;entity resolution : commencer par les identifiants fiables, étendre avec des correspondances directes, puis utiliser la théorie des graphes pour gérer les relations multiples. La détection automatique des incohérences maintient la qualité des données tout en identifiant les cas nécessitant une intervention manuelle.\n","date":"14 octobre 2025","externalUrl":null,"permalink":"/articles/entity_resolution/","section":"Articles","summary":"Le défi de l’identification des bénéficiaires # L’écosystème de la santé rassemble plusieurs types d’acteurs : laboratoires pharmaceutiques, professionnels de santé et associations de patients. Ces acteurs entretiennent entre eux des relations financières et d’influence qui peuvent créer des conflits d’intérêt.\n","title":"Déduplication de données : utilisation de la résolution d'entités sur la base Transparence Santé","type":"articles"},{"content":" La qualité des données est un enjeu central dans l\u0026rsquo;exploitation des bases de données publiques. Dans le cadre du projet EurosForDocs, qui vise à apporter de la transparence sur les liens financiers entre entreprises du médicament et professionnels de santé, cet enjeu est particulièrement critique. La fiabilité des analyses repose sur notre capacité à identifier sans ambiguïté chaque professionnel de santé recevant une rémunération ou un avantage.\nLe RPPS (Répertoire Partagé des Professionnels de Santé) est un répertoire étatique national qui recence l\u0026rsquo;ensemble des professionnels de santé en France et leur attribue un numéro unique et public. Ce numéros est par exemple visible dans la partie \u0026ldquo;Informations légales\u0026rdquo; page d’un praticien sur Doctolib, ou sur une ordonnance. En théorie, le numéro RPPS devrait garantir une association fiable entre une déclaration de rémunération d\u0026rsquo;un entreprise et un professionnel de santé. Il est donc essentiel de s\u0026rsquo;assurer que cette information soit la plus juste possible. Cependant, en pratique, les erreurs de saisie sont fréquentes. Il n\u0026rsquo;est pas rare qu\u0026rsquo;un même professionnel se voit attribuer plusieurs numéros RPPS par une même entreprise, créant ainsi des conflits qui faussent l\u0026rsquo;analyse.\nCet article présente une méthodologie pour détecter et corriger ces incohérences à grande échelle. Nous y détaillons une approche de fuzzy matching qui consiste à mesurer la similarité entre les données déclarées et celles d\u0026rsquo;une source officielle. Selon le niveau de similarité mesuré, on peut alors corriger les données. Cette méthode permet d\u0026rsquo;automatiser le nettoyage des identifiants et d\u0026rsquo;améliorer significativement la qualité de la base de données.\nPour une vision plus générale des enjeux de qualité des données du projet EurosForDocs, vous pouvez consulter cet article.\nLe problème : des identifiants uniques qui ne le sont pas # Le numéro RPPS est la clé de voûte du système de déclaration. Chaque professionnel de santé devrait être associé à un numéro unique pour garantir une identification fiable à travers différentes déclarations de différentes entreprises.\nToutefois, la réalité des données est plus complexe. Nous constatons de nombreux cas pour lesquels une même entreprise déclare plusieurs rémunérations avec les même nom, prénom, profession et code postal de bénéficiaire (ce qui semble indiquer la même personne) mais avec des numéros RPPS différents. Cette situation crée une ambiguïté : s\u0026rsquo;agit-il d\u0026rsquo;une erreur de saisie ou de deux professionnels distincts mais homonymes ?\nPour lever le doute, la procédure consiste à comparer les informations officielles liées à chaque numéro RPPS déclaré avec les autres informations déclarées par l\u0026rsquo;entreprise. Cette démarche permet d\u0026rsquo;identifier des numéros RPPS absurdes par rapport aux informations déclarées, et de déterminer le numéro qui semble le plus pertinent par rapport à la déclaration.\nPrenons un exemple concret :\nUn laboratoire déclare un bénéficiaire, \u0026ldquo;Jean Crochet\u0026rdquo;, en lui associant deux numéros RPPS : 10002956406 et 10003257325.\nLe répertoire RPPS confirme que le numéros ...406 appartient bien au Dr. Jean Crochet, médecin exerçant dans le département déclaré. Les informations sont cohérentes. En revanche, le numéro ...325 est attribué au Dr. Nathalie Bourgeois, une autre praticienne. Les informations sont clairement incohérentes. Ce simple croisement suffit à invalider le second numéro RPPS et à résoudre l\u0026rsquo;ambiguïté. Le défi n\u0026rsquo;est pas conceptuel mais opérationnel : avec plus de 12 500 cas similaires identifiés, et de nouveaux cas pouvant apparaître quotidiennement, un traitement manuel est inenvisageable. Il est donc nécessaire de développer une méthode automatisée pour appliquer ce raisonnement de manière systématique et fiabiliser la base de données.\nUne approche souple : la similarité textuelle # La simple vérification des identifiants se heurte rapidement à une autre réalité : les informations déclarées (nom, prénom) sont souvent proches mais pas strictement identiques à celles du répertoire. Une coquille, une inversion entre nom et prénom, ou l\u0026rsquo;utilisation d\u0026rsquo;un nom d\u0026rsquo;usage peuvent suffire à invalider à tort un rapprochement.\nPar exemple, un médecin \u0026ldquo;Jean-Luc Vilatte\u0026rdquo; est déclaré avec deux numéros RPPS. Le répertoire officiel indique qu\u0026rsquo;un numéro appartient à \u0026ldquo;Jean-Luc Vallet\u0026rdquo; et l\u0026rsquo;autre à \u0026ldquo;Jean-Luc Villate\u0026rdquo;. Une comparaison stricte rejetterait les deux options. Cependant, de nombreux algorithmes proposent différentes manières de mesurer de la similarité entre deux chaines de caractère. Le projet EurosForDocs a choisi de travailler avec la métrique de Jaro-Winkler. La définition exacte de cette métrique n\u0026rsquo;étant pas l\u0026rsquo;objectif de cet article, les lecteurs curieux pourront se référer à cet article. En utilisant cette métrique, on mesure pour \u0026ldquo;Villate\u0026rdquo; 97% de similarité envers \u0026ldquo;Vilate\u0026rdquo; mais seulement 74% envers \u0026ldquo;Vallet\u0026rdquo;. Cette métrique nous permet donc d\u0026rsquo;identifier le nom qui correspond le moins à la déclaration.\nPlutôt que de chercher une correspondance exacte, notre méthode va donc créer un score de similarité entre les informations déclarées et les informations officielles. Ce score est défini comme la somme entre la similarité des prénoms et la similarité des noms. Un numéro RPPS absurde aura donc un score de similarité proche de zéro alors qu\u0026rsquo;une déclaration parfaite aura un score de 2 (100% pour chaque partie de l\u0026rsquo;identité). Cette approche, connue sous le nom de fuzzy matching, offre la flexibilité nécessaire pour gérer différents types d\u0026rsquo;erreurs de saisie.\nGérer les erreurs de saisie courantes # Il est à noter que même dans le répertoire RPPS, un même professionnel peut apparaître sous plusieurs noms. Un cas typique est la présence de docteures qui apparaissent avec différentes combinaisons de leur nom de jeune fille et de leur nom d’épouse. Dans ce cas, nous calculons le score de similarité pour toutes les variations. Le meilleur score de chaque numéro RPPS servira à identifier le numéro le plus pertinent.\nMais il existe également différents types d\u0026rsquo;erreur de saisie qui donnent de mauvais scores de similarité et ne permettent pas de sélectionner correctement le numéro RPPS correct.\nLes inversions nom/prénom : Il arrive que les champs noms et prénom soient inversés lors de la saisie. Pour neutraliser cet effet, nous calculons la similarité à la fois sur nom/prénom et sur prénom/nom (en plus des traditionnels nom/nom et prénom/prénom), et nous retenons le score le plus favorable.\nLes noms et prénoms composés : Un professionnel nommé \u0026ldquo;Loriot De Rouvray\u0026rdquo; peut être déclaré simplement comme \u0026ldquo;De Rouvray\u0026rdquo;. Utiliser directement la métrique de Jaro-Winkler ne donnerait que 42% de similarité; ce qui est très faible. Pour résoudre ce cas, nous utilisons une métrique personnalisée : on compte le nombre de mots en commun entre le nom déclaré et l\u0026rsquo;officiel, divisé par le plus petit nombre de mots dans l\u0026rsquo;un des deux noms. Ainsi, \u0026ldquo;De Rouvray\u0026rdquo; et \u0026ldquo;Loriot De Rouvray\u0026rdquo; obtiennent une similarité de 100%. En effet les deux noms ont deux mots en commun (\u0026ldquo;De\u0026rdquo; et \u0026ldquo;Rouvray\u0026rdquo;) et le plus petit nom contient également deux mots. La même logique s\u0026rsquo;applique aux prénoms, permettant de reconnaître \u0026ldquo;Jean\u0026rdquo; comme une version courte de \u0026ldquo;Jean-Luc\u0026rdquo;.\nLa similarité finale est alors une combinaison des différents facteurs décrits plus tôt. Le calcul se décompose en plusieurs étapes pour obtenir un score de similarité global.\nL\u0026rsquo;objectif est de construire un score robuste qui prend en compte les différentes manières dont un nom et un prénom peuvent être saisis.\nÉvaluation de la similarité pour le nom et le prénom Pour le nom de famille, on calcule deux scores distincts : la métrique de Jaro-Winkler et le score de composition. On retient ensuite la valeur la plus élevée des deux. Cette opération est répétée pour le prénom. On dispose alors d\u0026rsquo;un score de similarité pour le nom, et d\u0026rsquo;un autre pour le prénom.\nCalcul d\u0026rsquo;un score de \u0026ldquo;similarité directe\u0026rdquo; On additionne les deux scores obtenus à l\u0026rsquo;étape précédente. Ce total représente notre score de similarité lorsque l\u0026rsquo;on suppose que l\u0026rsquo;entreprise déclarante n\u0026rsquo;a pas inversé le nom et le prénom du bénéficiaire.\nPrise en compte de l\u0026rsquo;inversion nom/prénom Pour gérer les cas où le nom et le prénom auraient été inversés lors de la saisie, on calcule un score de \u0026ldquo;similarité inversée\u0026rdquo;. Pour ce faire, on compare le nom de famille déclaré avec le prénom officiel, et inversement, en utilisant la métrique de Jaro-Winkler. Contrairement à la similarité directe, on ne prend pas en compte ici de score de composition pour ne permettre qu\u0026rsquo;une seule \u0026ldquo;erreur\u0026rdquo; de la part de l\u0026rsquo;entreprise déclarante et limiter le risque d\u0026rsquo;obtenir un bon score par chance.\nDétermination du score final Le score de similarité final est simplement le maximum entre le score de similarité directe et le score de similarité inversée.\nAffiner le score : variables contextuelles et seuil de confiance # Si la similarité des noms et prénoms est un excellent indicateur, elle ne suffit pas toujours. Deux cas de figure nécessitent des ajustements pour garantir la fiabilité de la méthode : la gestion des homonymes et celle des données de très mauvaise qualité.\nLa gestion des homonymes : le besoin d\u0026rsquo;informations contextuelles # La méthode atteint sa limite face à de vrais homonymes : deux professionnels distincts portant le même nom et prénom; c\u0026rsquo;est à dire ayant le même score de similarité. Pour les départager, il est indispensable d\u0026rsquo;utiliser des informations contextuelles supplémentaires :\nLe code postal La profession Le département d\u0026rsquo;exercice Toutefois, ces variables doivent être utilisées avec précaution. Une correspondance sur le code postal ne doit pas surcompenser un nom et un prénom très différents. Nous les intégrons donc comme de légers bonus venant pondérer le score de similarité. Une égalité entre le code postal du répertoire des professionnels et celui de la déclaration augmente la métrique de similarité de 0.04. De même, une égalité des profession ajoute 0.02 à la similarité. Finalement une égalité du département d\u0026rsquo;exercice ajoute 0.01 à la similarité. Ces valeurs ont été choisies arbitrairement suite à l\u0026rsquo;exploration des données; l\u0026rsquo;objectif étant de départager deux candidats très similaires, mais insufisamment pour faire passer un nom complètement incohérent devant un nom plus pertinent uniquement grâce à un code postal ou une profession.\nLe seuil de validité : se prémunir contre les données aberrantes # Parfois, aucun des bénéficiaires liés aux numéros RPPS déclarés ne semblent convenir. Par exemple, une déclaration pour l\u0026rsquo;infirmière \u0026ldquo;Karine NOREILS\u0026rdquo; est associée à deux numéros RPPS qui, d\u0026rsquo;après le répertoire, correspondent à deux médecins : \u0026ldquo;Christophe Michiels\u0026rdquo; et \u0026ldquo;Bernard Duclos\u0026rdquo;. Les noms, prénoms et professions sont si éloignés qu\u0026rsquo;aucune correspondance n\u0026rsquo;est acceptable.\nPour éviter de créer des liens erronés dans de tels cas, nous avons défini un seuil de similarité minimum. Si le meilleur score obtenu n\u0026rsquo;atteint pas ce seuil (fixé arbitrairement à 1.7), aucune décision n\u0026rsquo;est prise. L\u0026rsquo;ambiguïté est conservée et le cas est signalé pour une analyse approfondie. Ce garde-fou est essentiel pour garantir que seules les corrections présentant un haut degré de confiance sont automatisées.\nMise en perspective et conclusion # La méthodologie décrite ici est une application concrète des techniques de fuzzy matching à un problème de qualité de données. Elle illustre qu\u0026rsquo;une approche simple et pragmatique, combinant un algorithme de similarité standard avec des règles métier ciblées, permet de résoudre une grande partie des ambiguïtés de manière automatisée.\nSur l\u0026rsquo;ensemble des bénéficiaires présentant une ambiguïté de numéro RPPS, ce système nous permet d\u0026rsquo;en résoudre plus de 95% avec un haut degré de confiance. Les cas restants, souvent les plus complexes, sont signalés pour une analyse approfondie.\nCette approche montre l\u0026rsquo;importance d\u0026rsquo;adapter les outils de data science au contexte métier. Une connaissance fine des données et des sources d\u0026rsquo;erreurs potentielles (homonymes, noms composés) est indispensable pour construire une solution de nettoyage à la fois robuste et fiable.\n","date":"18 août 2025","externalUrl":null,"permalink":"/articles/clean_rpps_fuzzy/","section":"Articles","summary":"La qualité des données est un enjeu central dans l’exploitation des bases de données publiques. Dans le cadre du projet EurosForDocs, qui vise à apporter de la transparence sur les liens financiers entre entreprises du médicament et professionnels de santé, cet enjeu est particulièrement critique. La fiabilité des analyses repose sur notre capacité à identifier sans ambiguïté chaque professionnel de santé recevant une rémunération ou un avantage.\n","title":"Application du fuzzy matching pour la désambiguïsation de professionnels de santé","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":"28 juillet 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":"28 juillet 2025","externalUrl":null,"permalink":"/tags/optimisation-sous-contrainte/","section":"Tags","summary":"","title":"Optimisation Sous Contrainte","type":"tags"},{"content":"","date":"28 juillet 2025","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","date":"1 juillet 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":"1 juillet 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":"1 juillet 2025","externalUrl":null,"permalink":"/tags/polars/","section":"Tags","summary":"","title":"Polars","type":"tags"},{"content":"","date":"27 mai 2025","externalUrl":null,"permalink":"/tags/eurosfordocs/","section":"Tags","summary":"","title":"EurosForDocs","type":"tags"},{"content":" Un scandale qui a tout changé # En 2010, la pneumologue Irène Frachon publie le livre Mediator 150 mg : combien de morts ? et déclenche le scandale du Mediator en France. De 1976 à 2009, ce médicament apparenté aux amphétamines a été prescrit comme coupe-faim alors que son autorisation n\u0026rsquo;était limitée qu\u0026rsquo;au traitement du diabète de type 2. Les conséquences ont été dramatiques : environ 2000 décès et de nombreux patients souffrant d\u0026rsquo;effets secondaires graves, en particulier des lésions cardio-vasculaires.\nFace à ce désastre sanitaire, une loi relative au renforcement de la sécurité sanitaire du médicament et des produits de santé a été votée en 2011 pour imposer une nouvelle obligation aux laboratoires pharmaceutiques et entreprises du secteur de la santé : déclarer publiquement tout versement financier ou avantage en nature accordé aux professionnels de santé, hôpitaux ou associations liées à la santé. Cette mesure vise à rendre visibles les liens d\u0026rsquo;intérêt qui pourraient influencer les pratiques médicales. Une plateforme gouvernementale, Transparence Santé, a été mise en ligne pour centraliser ces déclarations et les mettre à disposition du public sous forme de données ouvertes (Open Data).\nUne transparence difficilement exploitable # Des données de mauvaise qualité # Si l\u0026rsquo;intention derrière la plateforme Transparence Santé est louable et unique en Europe, d\u0026rsquo;importantes lacunes rendent difficile son utilisation par les citoyens. Imaginons que vous cherchiez des informations sur un médecin nommé \u0026ldquo;Leurent\u0026rdquo;. Voici ce que vous verriez sur la plateforme gouvernementale :\nUn problème saute aux yeux immédiatement: plusieurs médecins apparaissent plusieurs fois dans les résultats, avec de légères variations. On trouve des entrées dupliquées à cause de différences mineures d\u0026rsquo;orthographe, de villes voisines mentionnées, ou de simples erreurs de saisie. Pour quelqu\u0026rsquo;un qui souhaite connaître les liens d\u0026rsquo;intérêt d\u0026rsquo;une personne précise, il devient difficile d\u0026rsquo;obtenir une image complète de la situation.\nCe problème est symptomatique d\u0026rsquo;un manque de bonnes pratiques dans la création de la base de données, que ce soit au niveau de la plateforme comme des laboratoires déclarants. Les bénéficiaires des avantages et rémunérations possèdent pourtant tous un identifiant national unique: le RPPS pour les professionnels de santé et le SIREN pour les associations et autres personnes morales. Il est alors aisé d\u0026rsquo;utiliser ces identifiants et leurs annuaires respectifs pour assurer une cohérence dans les données des bénéficiaires. Malheureusement, seules 50% des déclarations ont effectivement un identifiant de renseigné. Une évolution de la plateforme en 2022 a néanmoins permis d\u0026rsquo;augmenter l\u0026rsquo;utilisation du RPPS à 90%; sans cependant impacter les données relatives aux associations qui reçoivent pourtant l\u0026rsquo;essentiel des avantages et rémunérations.\nUn manque d\u0026rsquo;ergonomie # Poursuivons notre exemple en cliquant sur la page du docteur Bernard Leurent, qui ne semble pas dupliqué. Nous arrivons alors à une page qui se contente de lister toutes les déclarations relatives à ce bénéficiaire sous forme de liste.\nPour simplement connaître le montant total reçu par le bénéficiaire, il est nécessaire de télécharger au format CSV les déclarations et utiliser excel pour faire la somme des montants. Il est à noter qu\u0026rsquo;il peut être nécessaire de combiner plusieurs excels si le bénéficiaire a plusieurs comptes. Cette recherche d\u0026rsquo;information peut très rapidement devenir fastidieuse. Connaitre la répartition par entreprise est rendu encore plus compliquée par la qualité des données, une entreprise pouvant déclarer à travers différents comptes et filiales ne partageant pas nécessairement le même nom.\nLa base Transparence Santé sombre alors dans une situation paradoxale. Bien que proposant techniquement des données en libre accès, la qualité des données et l\u0026rsquo;interface utilisateur sont des freins significatifs à l\u0026rsquo;utilisation de ces données par la société civile.\nEurosForDocs : une solution pour une véritable transparence # Face à ce constat, l\u0026rsquo;association EurosForDocs a été créée par deux utilisateurs de Transparence Santé pour tenter d\u0026rsquo;améliorer la situation. En se basant sur les données publiques de Transparence Santé, EurosForDocs poursuit trois objectifs principaux :\nOffrir une plateforme d\u0026rsquo;exploration conviviale : Disponible gratuitement sur eurosfordocs.fr, elle permet à chacun de consulter facilement les liens d\u0026rsquo;intérêt entre laboratoires pharmaceutiques et différents bénéficiaires. Nettoyer et améliorer les données : L\u0026rsquo;équipe travaille à normaliser voire corriger les données. L\u0026rsquo;identification et la fusion de doublons dans les bénéficiaires joue un rôle important pour l\u0026rsquo;usabilité de la base de données. Accompagner les chercheurs et journalistes : EurosForDocs offre son expertise pour aider ceux qui souhaitent analyser ces données en profondeur, contribuant ainsi au débat public sur la transparence en santé. Quelques exemples de contribution sont donnés en fin d\u0026rsquo;article. Pour répondre au premier objectif de l\u0026rsquo;association, un tableau de bord permet de rapidement se faire une idée générale de la situation. Le résultat pour le docteur Bernard Leurent propose automatiquement plusieurs visualisations : montant total reçu, répartition des versements par entreprise, évolution des sommes au fil des années, et motifs des paiements. Pour des analyses plus poussées, le détail des déclarations est également disponible et téléchargeable.\nUne chaîne de traitement pour transformer les données # La base Transparence Santé souffre de nombreux problèmes de qualité. Le cœur du défi technique d\u0026rsquo;EurosForDocs est alors de corriger ces données pour les rendre plus fiables et exploitables. Pour cela, nous avons mis en place un processus automatisé qui se déclenche chaque matin. Il commence par télécharger la dernière version de Transparence Santé, puis la fait passer par plusieurs étapes de nettoyage et d\u0026rsquo;amélioration. Finalement, les données nettoyées sont mise à disposition sur notre site à travers notre tableau de bord ou directement en fichier CSV. Techniquement, notre solution repose sur un code python qui orchestre des requêtes SQL qui transforment la donnée.\nDuckDB est utilisé comme moteur de traitement de données. Cette variante de SQL regroupe plusieurs caractéristiques utiles à ce projet:\nElle est optimisée pour des traitements massifs. Elle ne nécessite pas d\u0026rsquo;infrastructure particulière : les données sont stockées localement sur de simples fichiers. Elle peut s\u0026rsquo;adapter à de petites machines : on peut donc utiliser les serveurs cloud les moins chers. L\u0026rsquo;utilisation de cette technologie nous permet de traiter les millions de déclarations efficacement, à moindre coût, et de maintenir une latence faible sur notre tableau de bord.\nPar soucis de transparence, notre code source est entièrement public. Toute personnes avec des compétences en python et SQL peut télécharger le code, lancer le traitement de données sur sa machine et auditer les différentes transformations.\nNotre processus de correction des données se découpe principalement en 4 parties.\nLa déduplication des entreprises : Nous regroupons les différentes filiales et comptes multiples d\u0026rsquo;une même entreprise pour obtenir une vision consolidée. La déduplication des bénéficiaires : Nous identifions et fusionnons les entrées multiples qui correspondent à un même professionnel de santé ou une même organisation. La normalisation des motifs : Nous standardisons les raisons déclarées pour les versements afin de permettre des analyses cohérentes. La mise en relation des déclarations : Nous améliorons les liens entre les différents versements et les conventions dans lesquelles ils doivent s\u0026rsquo;inscrire. Un système de déduplication d\u0026rsquo;entreprises presque fonctionnel # Dans le système de Transparence Santé, une même entreprise déclarante peut apparaître sous plusieurs identités différentes. Chaque filiale peut effectuer ses propres déclarations, parfois même via plusieurs comptes distincts. Ces différents comptes ont le plus souvent des noms différents. Il devient alors plus complexe de comprendre les enjeux de liens d\u0026rsquo;intérêt lorsque le même laboratoire apparait sous plusieurs variantes. En théorie, la plateforme gouvernementale a prévu un mécanisme de déduplication. Il est possible de déclarer qu\u0026rsquo;un compte entreprise appartient à un groupement en renseignant l\u0026rsquo;identifiant d\u0026rsquo;un compte de référence (ou entreprise mère). Fusionner les comptes reliés à la même entreprise mère devrait permettre de normaliser les noms des entreprises déclarantes. On obtient alors des données plus compréhensibles. Malheureusement les entreprises déclarantes manquent de rigueur dans l\u0026rsquo;utilisation de ce mécanisme. Après fusion des comptes liés, de nombreux doublons persistent dans la base de données et nécessitent un nettoyage.\nLe secteur médical ne regroupe que relativement peu d\u0026rsquo;entreprises, avec seulement 4850 comptes d\u0026rsquo;entreprises déclarés dans Transparence Santé. De plus, on s\u0026rsquo;attend à ce que les entreprises réutilisent au maximum les comptes de déclaration existants. La création de nouveau comptes devrait être occasionnelle : création de filiale ou de nouveau service, turnover de personnel, etc\u0026hellip; Dans ces conditions, une vérification semi manuelle des doublons est encore possible.\nL\u0026rsquo;image suivante montre un document de travail pour la déduplication manuelle. Pour chaque entreprise, l\u0026rsquo;entreprise mère déclarée est documentée dans la colonne E. L\u0026rsquo;équipe EurosForDocs peut attribuer un compte de référence à une entreprise déclarante dans la colonne H. Le surlignage bleu montre par exemple les différentes filiales du groupe 3M, dont certaines étaient automatiquement reliées à la maison mère française et d\u0026rsquo;autre considérées comme des entreprises indépendantes. Finalement, à travers ce système mixte de déduplication, près de 900 comptes sont fusionnés.\nDéduplication des bénéficiaires : la guerre des clones # Le plus grand défi technique d\u0026rsquo;EurosForDocs concerne l\u0026rsquo;identification unique des bénéficiaires dans la base de données. Contrairement aux entreprises qui sont quelques milliers, nous devons ici traiter plus de 26 millions de bénéficiaires déclarés potentiellement dupliqués. En théorie, la solution paraît simple : chaque professionnel de santé possède un numéro d\u0026rsquo;identification officiel (RPPS ou ADELI) et chaque organisation dispose d\u0026rsquo;un numéro d\u0026rsquo;entreprise (SIREN) ou d\u0026rsquo;association (RNA). Malheureusement, dans la pratique, ces identifiants sont rarement renseignés correctement dans les déclarations. Notre mission consiste donc à tenter d\u0026rsquo;attribuer un identifiant officiel à chaque déclaration qui n\u0026rsquo;en contient pas.\nNotre analyse révèle deux situations bien distinctes :\nLes personnes physiques (médecins, infirmiers, etc\u0026hellip;) : Nous disposons de plusieurs éléments pour les identifier(nom, prénom, profession, code postal). Nous pouvons croiser ces données avec l\u0026rsquo;annuaire national des professionnels de santé pour tenter d\u0026rsquo;attribuer un numéro RPPS ou ADELI à chaque bénéficiaire. Les personnes morales (associations, hôpitaux, etc\u0026hellip;) : Seuls le nom et parfois le numéro SIREN ou RNA sont disponibles. Les noms d\u0026rsquo;organisations étant beaucoup moins standardisés que les noms de famille, leur déduplication automatique reste un défi que nous n\u0026rsquo;avons pas encore résolu. Un système de déduplication manuelle est néanmoins en place pour des besoins ponctuels. Réduction de bénéficiaire par cohérence de déclaration # Pour chaque nouvelle déclaration concernant un même bénéficiaire, les entreprises doivent répéter les informations le concernant. On peut alors considérer qu\u0026rsquo;une entreprise qui déclare le même nom, prénom, profession et code postal de bénéficiaire entre deux déclarations fait référence à la même entité. Ces informations définissent alors un compte bénéficiaire, identifié par un numéros efd_id. Nous avons cependant observé que pour un même compte bénéficiaire, des identifiants différents peuvent être renseignés. Par exemple, le compte correspondant à Jean Crochet possède deux RPPS différents.\nNous avons alors analysé en détail ces comptes. A partir des annuaires dédiés à chaque type d\u0026rsquo;identifiant, nous avons pu comparer les informations officielles liées à chaque identifiant avec celles déclarées dans Transparence Santé. Systématiquement, un seul des identifiants correspond aux valeurs des annuaires. En définissant une notion de similarité à partir du nom, prénom, de la profession et du code postal, on peut identifier automatiquement les RPPS absurdes. Dans le cas de Jean Crochet, un des RPPS correspond en réalité à Nathalie Bourgeois; ce qui conduit à un score de similarité bien inférieur à celui correspondant au RPPS correct. Nous nettoyons alors la base de données pour ne garder que les identifiants corrects.\nComment identifier un professionnel de santé parmi les doublons? # Puisque les entreprises peuvent saisir librement les informations concernant les bénéficiaires, sans format imposé, de nombreuses variations et erreurs sont présentes pour une même personne. EurosForDocs a défini une stratégie en 3 étapes pour tenter de regrouper les comptes bénéficiaires dupliqués en une seule entité.\nAttribuer des identifiants manquants : Pour les bénéficiaires sans numéro RPPS, nous essayons de faire correspondre leurs informations avec l\u0026rsquo;annuaire officiel des professionnels des santé. Nous commençons par les cas les plus simples (correspondance exacte de tous les champs) avant d\u0026rsquo;assouplir progressivement nos critères pour traiter les cas plus ambigus, comme les inversions nom/prénom ou les noms composés partiellement déclarés. Il est à noter que nous n\u0026rsquo;attribuons pas de RPPS si les critères identifient plusieurs professionnels différents dans l\u0026rsquo;annuaire.\nRegrouper les comptes similaires : Certains bénéficiaires ne peuvent pas être liés à un identifiant officiel mais partagent les mêmes informations. Par exemple, deux bénéficiaires qui partagent le même nom, prénom et profession et qui n\u0026rsquo;ont pas de RPPS sont considérés comme des doublons. Cette méthode est moins fiable mais ne s\u0026rsquo;applique alors qu\u0026rsquo;aux comptes pour lesquels l\u0026rsquo;identification à partir de l\u0026rsquo;annuaire santé a échoué.\nFusionner tous les duplicatas : Les deux étapes précédentes ont permis de créer des liens entre les différents comptes. L\u0026rsquo;étape 1 permet de créer des liens indirect (via les RPPS, SIREN, etc\u0026hellip;). L\u0026rsquo;étape 2 permet de relier directement deux comptes. Un algorithme de traitement de réseaux sociaux va alors regrouper tous les comptes qui appartiennent à la même communauté isolée. Chaque communauté est alors considérée comme un bénéficiaire unique et tous les comptes en faisant parti seront fusionnés. Dans l\u0026rsquo;exemple suivant, les comptes bénéficiaires (en bleu clair) créent trois communautés distinctes à travers les liens entre eux (les comptes 10 et 3 en bas de l\u0026rsquo;image) ou leur lien à un RPPS ou compte ADELI.\nCette stratégie de déduplication nous permet de réduire considérablement le nombre de doublons. Sur plus de 6 millions de comptes de professionnels de santé, 1.6 millions demeurent après la déduplication. Il reste probablement une quantité significative de doublons parmi nos bénéficiaires finaux puisque 780 000 comptes n\u0026rsquo;ont à ce jour aucun identifiant.\nLe défi de la normalisation des motifs de versement # À l\u0026rsquo;origine, les entreprises pharmaceutiques documentaient les raisons de leurs versements aux professionnels de santé dans un simple champ de texte libre. Cette absence de standardisation rendait l\u0026rsquo;analyse des données pratiquement impossible. Les motifs variaient considérablement d\u0026rsquo;une déclaration à l\u0026rsquo;autre : allant de descriptions détaillées de conférences spécifiques à de simples mentions comme \u0026ldquo;repas\u0026rdquo;, voire restant entièrement vides. Pour remédier à cette situation, une mise à jour de la plateforme Transparence Santé en 2022 a introduit une nomenclature de 48 valeurs de motifs. Cependant, malgré cette amélioration, de nombreuses entreprises contournent cette standardisation en sélectionnant simplement la catégorie \u0026ldquo;AUTRE\u0026rdquo; puis en renseignant dans un champ complémentaire leurs descriptions personnalisées. Certains \u0026ldquo;AUTRE\u0026rdquo; motifs correspondent même exactement à l\u0026rsquo;une des 48 catégories officielles. L\u0026rsquo;image suivante nous montre ainsi la variété de motifs \u0026ldquo;AUTRE\u0026rdquo; que l\u0026rsquo;on va chercher à normaliser. Face à ce défi, EurosForDocs a développé une approche combinant traitements manuels et analyses automatisées par mots-clés. On passe alors de 18 millions des motifs non renseignés à 1.2 millions.\nRelier les paiements aux contrats : une comptabilité plus précise # Dans le système de transparence des liens d\u0026rsquo;intérêts, les laboratoires pharmaceutiques doivent d\u0026rsquo;abord déclarer un contrat (convention) avec un professionnel de santé en précisant le montant global prévu, puis déclarer séparément chaque paiement réel effectué dans le cadre de ce contrat. On a donc une problématique de double comptage des montants : une fois dans la convention en tant que montant prévisionnel et une fois pour le paiement réel. Pour éviter ces doubles comptages, EurosForDocs déduit du montant des conventions les montants réels des rémunération et avantages liés. Le montant final d\u0026rsquo;une convention que nous affichons est alors le reliquat, ou reste à dépenser de la convention.\nPour obtenir la vision la plus précise possible de ces reliquats (et donc réduire les risque de double comptage), il faut s\u0026rsquo;assurer que tous les paiements réels soient effectivement reliés à une convention. En pratique, de nombreux paiements apparaissent sans lien avec leur contrat initial. EurosForDocs tente alors de relier les rémunérations et avantages orphelins à des conventions et étant plus permissif sur l\u0026rsquo;entreprise déclarante et le compte bénéficiaire.\nConclusion # La plateforme Transparence Santé est un grand pas en avant vers une plus grande transparence dans l\u0026rsquo;industrie pharmaceutique. La qualité des données limite cependant le potentiel de la plateforme. Des initiatives comme EurosForDocs montrent qu\u0026rsquo;il est possible de transformer des données brutes et peu fiables en informations claires et exploitables. Mais cela nécessite un travail de nettoyage méticuleux et une approche rigoureuse. Ce projet illustre non seulement les défis techniques de la gestion des données, mais aussi l\u0026rsquo;importance de rendre ces informations accessibles et compréhensibles pour tous; afin de garantir une véritable transparence dans le domaine de la santé. Dans un monde de plus en plus dépendant des données, il est essentiel que nous ne nous contentions pas de rendre les données disponibles, mais que nous les rendions également utilisables, compréhensibles et fiables.\nExemples de collaborations # Vaccin contre la grippe : la recommandation des sociétés de gériatrie manque de transparence\nAddictions au sexe et aux jeux : des malades de Parkinson s\u0026rsquo;estiment floués par un labo\nMarchandage et lobbying : les dessous de l\u0026rsquo;annonce du milliard de Sanofi\nRessources supplémentaires # Le scandale du Mediator / Mytho-théories - Info ou Mytho ","date":"27 mai 2025","externalUrl":null,"permalink":"/projets/eurosfordocs/","section":"Projets","summary":"Un scandale qui a tout changé # En 2010, la pneumologue Irène Frachon publie le livre Mediator 150 mg : combien de morts ? et déclenche le scandale du Mediator en France. De 1976 à 2009, ce médicament apparenté aux amphétamines a été prescrit comme coupe-faim alors que son autorisation n’était limitée qu’au traitement du diabète de type 2. Les conséquences ont été dramatiques : environ 2000 décès et de nombreux patients souffrant d’effets secondaires graves, en particulier des lésions cardio-vasculaires.\n","title":"EurosForDocs ou comment renforcer la transparence dans la santé","type":"projets"},{"content":"","date":"27 mai 2025","externalUrl":null,"permalink":"/tags/transparence/","section":"Tags","summary":"","title":"Transparence","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":"16 février 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":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/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"}]