strayMat / sndsTools

https://straymat.github.io/sndsTools/
Other
0 stars 2 forks source link

Gestion des identifiants patients #28

Open abelloir-zz opened 2 weeks ago

abelloir-zz commented 2 weeks ago

En l'état la stratégie de gestion des identifiants est la suivante :

1) Sur la base de critères d'extractions (exemple : récupérer tous les patients ayant eu une délivrance d'anti-démence ou un séjour hospitalier pour la maladie d'Alzheimer) des BEN_NIR_PSA (dans le DCIR) ou NIR_ANO_17 (dans le PMSI) sont récupérés

2) Dans l'ébauche de pipeline de gestion des identifiants, les BEN_NIR_PSA associés à plusieurs BEN_IDT_ANO sont exclus (c'est un peu plus fin que ça en réalité dans la version de DrugsSafer car le "anti join" est fait sur le BEN_IDT_ANO). Ainsi, après ce pipeline, une table des patients regroupant des BEN_IDT_ANO et leurs BEN_NIR_PSA correspondants est construite. On a à ce moment la garantie que les BEN_NIR_PSA présents pointent vers un BEN_IDT_ANO unique.

3) Dans une récupération postérieure de données concernant ces patients, les BEN_NIR_PSA uniquement sont utilisés, que ce soit pour le DCIR ou le PMSI

C'est un parti pris motivé par les arguments suivants :

J'ai par ailleurs commencé à rédiger un document au sujet de la gestion des identifiants : j'y ai résumé les biais auxquels on s'expose selon les méthodes que l'on choisit

Ce que je propose c'est de partir sur cette version simplifiée de gestion des identifiants, quitte à la faire évoluer plus tard pour permettre notamment des études spécifiques sur le DCIR uniquement qui utiliserait alors BEN_NIR_PSA + BEN_RNG_GEM et le grand régime pour faire le lien entre la table des prestations et la table des bénéficiaires.

Des remarques ou (remise en) questions concernant ce choix ?

ThomasSoeiro commented 2 weeks ago

Comme déjà dit ailleurs je ne suis favorable à ne pas récupérer le BEN_RNG_GEM dans le DCIR. A mon avis c'est mélanger 2 choses ici :

Proposition de stratégie alternative pour le couplage extraction - référentiel bénéficiaires propre (l'ordre des 2 premiers points est interchangeable, le référentiel peut d'ailleurs être utilisé pour plusieurs études) :

Ressources utiles :

abelloir-zz commented 2 weeks ago

Merci pour ta réponse Thomas ! J'aimerais discuter de quelques points :

ThomasSoeiro commented 2 weeks ago
  • De ce que j'ai compris, la clé primaire de IR_BEN_R n'est pas BEN_NIR_PSA + BEN_RNG_GEM car le rang gémellaire n'a de sens qu'au sein d'un grand régime : il faut y rajouter l'information d'un grand régime (premiers caractères de ORG_AFF_BEN). C'est ce que j'ai détaillé dans le document dont j'ai mis le lien plus haut. C'est un détail, cela veut juste dire que si l'on veut faire les choses proprement il faut aussi prendre en compte c

Pour être précis, c'est pas exact de parler de clé primaire parce que dans l'ensemble il y a très peu de contraintes (au sens BDD du terme) sur les tables dans le SNDS (d'où pas mal d'anomalies par la suite...) mais l'idée est bien que BEN_NIR_PSA + BEN_RNG_GEM "can reliably identify and distinguish between each individual record in a table":

library(DBI)
con <- dbConnect(odbc::odbc(), dsn = "IPIAMPR2")

# source : https://stackoverflow.com/a/9016712
pk <- "
SELECT cols.table_name, cols.column_name, cols.position, cons.status, cons.owner
FROM all_constraints cons, all_cons_columns cols
WHERE cols.table_name = 'IR_BEN_R'
AND cons.constraint_type = 'P'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
ORDER BY cols.table_name, cols.position;
"

# pas de vraie clé primaire définie pour IR_BEN_R
dbGetQuery(con, pk)
# [1] TABLE_NAME  COLUMN_NAME POSITION    STATUS      OWNER      
# <0 lignes> (ou 'row.names' de longueur nulle)

# mais BEN_NIR_PSA + BEN_RNG_GEM permettent de distinguer chaque ligne
dbGetQuery(
  con,
  "SELECT COUNT(*) FROM ir_ben_r;"
)
#    COUNT(*)
# 1 126719049

dbGetQuery(
  con,
  "WITH psa_gem AS (SELECT DISTINCT ben_nir_psa, ben_rng_gem FROM ir_ben_r) SELECT COUNT(*) from psa_gem;"
)
#    COUNT(*)
# 1 126719049

dbDisconnect(con)
  • Pour l'instant j'ai uniquement considéré la construction d'un référentiel propre qui se base sur des BEN_NIR_PSA en entrée uniquement. Ça prend déjà un peu de temps de décrire l'impact des différentes méthodes de gestion des identifiants en se basant uniquement sur le BEN_NIR_PSA en entrée, c'est ce que j'ai fait dans le document plus haut. Si on prend le cas d'une étude où la source d'identification des patients est à la fois le PMSI et le DCIR, pour construire un référentiel propre, il faut une méthode de gestion des identifiants qui gère à la fois des triplets BEN_NIR_PSA + BEN_RNG_GEM + grand régime, et des BEN_NIR_PSA isolés (ceux du PMSI). Il faut donc manipuler à la fois une notion de triplets qui identifient correctement un patient (ceux extraits du DCIR), et des triplets obtenus par jointure avec les BEN_NIR_PSA isolés, dont on ne sait pas s'ils appartiennent au patient dont le BEN_NIR_PSA isolé a été extrait. Cela demande de prendre un peu de temps pour faire ça proprement et je n'aurai de mon côté pas le temps de m'en occuper. Veux tu te pencher sur le sujet ? En attendant, la méthode basée sur les BEN_NIR_PSA en entrée uniquement peut être gardée comme méthode simplifiée temporaire : elle a l'avantage d'être simple et déjà implémentée sur la branche de construction du référentiel. Elle peut prendre en entrée les extractions davantage complètes du DCIR (que l'on fera en récupérant BEN_RNG_GEM et ORG_AFF_BEN) en en gardant uniquement les BEN_NIR_PSA
  • Qu'entends-tu par "faire ensuite le nettoyage de l'extraction sur la base de ce référentiel " ?

Pour moi, "construire un référentiel" = nettoyer IR_BEN_R pour retenir uniquement les bénéficiaire avec de la données de qualité (identifiant unique et données socio-démo non aberrantes) éligibles pour une étude épidémio. Pour cela je travaille sur l'entièreté de IR_BEN_R. C'est pas long si c'est bien écrit et c'est réutilisable pour plusieurs études. Donc construire un référentiel propre est indépendant de faire une extraction (on peut avoir des cas frontières selon les études où on tolérera des choses ou pas mais ne compliquons pas). Une fois qu'on a un référentiel, on peut faire la jointure extraction + référentiel (+ critères d'inclusion d'une étude en particulier, par exemple RG + > 18 ans + France métropolitaine, mais ça c'est à l'utilisateur final de gérer). Un exemple pour une étude en cours.

Du coup, si on suit cette logique, on pourra simplifier la construction du référentiel en brouillon (07618bb) qui (d'après une lecture très rapide) semble être pour le moment une traduction des macros "référentiel" de DRUGS-SAFER. Notamment pas besoin de joindre avec une table patient à cette étape (de mémoire d'après discussion avec Julien la façon de procéder est aussi parce qu'il voulait avoir les infos pour faire un flowchart complet ; ça me semble dispensable ici). J'avais fait une comparaison d'une méthode proche de ce que je propose ici et de leurs macros.

Veux tu te pencher sur le sujet ?

Pas pour écrire une fonction en {dplyr}, je ne pratique pas assez... Mais pas de problème pour donner des avis (qui n'engagent que moi, presque tout est discutable pour le SNDS !)

abelloir-zz commented 2 weeks ago

Je ne savais pas qu'il y avait une seule ligne par BEN_NIR_PSA + BEN_RNG_GEM, c'est très intéressant. Est ce que tu sais si cela vaut toujours si l'on fait l'union de IR_BEN_R avec IR_BEN_R_arc ?

https://github.com/strayMat/sndsTools/commit/07618bb32aed6aeaed15da206cb6b3dd491c7091 est effectivement une reproduction de DRUGS-SAFER, j'ai laissé les noms de fonctions et de table identiques pour pouvoir comparer au code d'origine.

À la base j'étais intéressé comme eux par faire un flowchart, mais ce n'est pas indispensable effectivement : on peut se contenter au moment de la jointure avec l'extraction de recenser le nombre d'identifiants de l'extraction qui ont des entrées correspondantes incorrecte avec des données démographiques incorrectes, sans plus de précision. J'aime bien l'idée d'un référentiel nettoyé dans sa globalité d'entrée de jeu, cela nous rapproche d'une situation ou le SNDS serait un peu plus propre dès le début.

Il faut juste garder en tête que la jointure d'une extraction de BEN_NIR_PSA et BEN_RNG_GEM, du DCIR avec le référentiel nettoyé, et la jointure d'une extraction de BEN_NIR_PSA du PMSI avec le référentiel nettoyé ne pourra pas se faire de la même manière à cause de la présence des jumeaux du même sexe, mais ce n'est pas d'une difficulté ou d'une complexité majeure. De plus il faudra faire la distinction entre une table d'identifiants patients "extraits" d'une part, et "extraits et exploitable pour le PMSI" d'autre part, où l'on aura supprimé les jumeaux du même sexe. Mais je pense que ça en vaudra la peine :)


edit (Thomas) : je me suis mélangé les pinceaux, j'ai édité ton commentaire au lieu de le citer.

ThomasSoeiro commented 2 weeks ago

Je ne savais pas qu'il y avait une seule ligne par BEN_NIR_PSA + BEN_RNG_GEM, c'est très intéressant. Est ce que tu sais si cela vaut toujours si l'on fait l'union de IR_BEN_R avec IR_BEN_R_arc ?

Je ne sais pas et je milite pour s'en débarrasser autant que possible vu l'historique qu'on a désormais et la qualité des données il y a > 10 ans (remontée des décès par exemple !).

À la base j'étais intéressé comme eux par faire un flowchart, mais ce n'est pas indispensable effectivement : on peut se contenter au moment de la jointure avec l'extraction de recenser le nombre d'identifiants de l'extraction qui ont des entrées correspondantes incorrecte avec des données démographiques incorrectes, sans plus de précision.

+1

Il faut juste garder en tête que la jointure d'une extraction de BEN_NIR_PSA et BEN_RNG_GEM, du DCIR avec le référentiel nettoyé, et la jointure d'une extraction de BEN_NIR_PSA du PMSI avec le référentiel nettoyé ne pourra pas se faire de la même manière à cause de la présence des jumeaux du même sexe, mais ce n'est pas d'une difficulté ou d'une complexité majeure. De plus il faudra faire la distinction entre une table d'identifiants patients "extraits" d'une part, et "extraits et exploitable pour le PMSI" d'autre part, où l'on aura supprimé les jumeaux du même sexe. Mais je pense que ça en vaudra la peine :)

Pas compris. Le but de nettoyer le référentiel c'est notamment de t'affranchir (entre autre) des problèmes de jumeaux de même sexe. Il faut que dans le référentiel nettoyé 1 BEN_IDT_ANO = 1 patient avec des données de qualités.

abelloir-zz commented 2 weeks ago

Dans les projets sur lesquels j'ai travaillé, il y avait souvent un intérêt d'aller constituer des cohortes à partir de 2010 inclus pour avoir des durées de suivi longues des patients. Sans travailler à proprement parler sur les données antérieures à 2010, on avait quand même besoin d'utiliser IR_BEN_R_arc : sans cette table on ne retrouvait pas une partie des patients (je ne me rappelle plus la proportion affectée). Je pense qu'il serait utile de vérifier cette règle 1 paire (BEN_NIR_PSA, BEN_RNG_GEM) = 1 ligne sur l'union de IR_BEN_R et IR_BEN_R_arc.

Sauf erreur, les jumeaux du même sexe peuvent gardés dans un référentiel nettoyé dans le cas où ils ont deux BEN_NIR_ANO distincts, parce qu'alors ils peuvent être distingués (leur BEN_IDT_ANO est égal à leur BEN_NIR_ANO)

ThomasSoeiro commented 2 weeks ago

Sauf erreur, les jumeaux du même sexe peuvent gardés dans un référentiel nettoyé dans le cas où ils ont deux BEN_NIR_ANO distincts, parce qu'alors ils peuvent être distingués (leur BEN_IDT_ANO est égal à leur BEN_NIR_ANO)

Oui on supprime les patients où 1 BEN_NIR_PSA = plusieurs BEN_NIR_ANO :

ThomasSoeiro commented 2 weeks ago

Top @abelloir-zz que tu creuses le sujet 👍

Je pense que c'est vraiment le plus important que bien réfléchir à la stratégie et qu'on prenne le temps d'évaluer les différentes options. La mienne n'est pas forcément la meilleure. C'est juste qu'à l'heure actuelle ça répond à mes besoins et ça me semble propre.

abelloir-zz commented 2 weeks ago

Mon point c'est que si tu travailles sur le DCIR uniquement et que tu prends dans ton extraction le BEN_NIR_PSA et le BEN_RNG_GEM, tu n'as pas besoin d'exclure les patients où 1 BEN_NIR_PSA = plusieurs BEN_NIR_ANO puisque tu peux justement les différencier avec le BEN_RNG_GEM. Sinon je ne vois pas trop l'intérêt de rapatrier les BEN_RNG_GEM dans l'extraction du DCIR

ThomasSoeiro commented 2 weeks ago

Mon point c'est que si tu travailles sur le DCIR uniquement et que tu prends dans ton extraction le BEN_NIR_PSA et le BEN_RNG_GEM, tu n'as pas besoin d'exclure les patients où 1 BEN_NIR_PSA = plusieurs BEN_NIR_ANO puisque tu peux justement les différencier avec le BEN_RNG_GEM.

Pas si le bénéficiaire change de régime

abelloir-zz commented 2 weeks ago

Il y a peut être quelque chose qui m'échappe : s'il change de régime, pourquoi son BEN_NIR_ANO changerait ?

ThomasSoeiro commented 2 weeks ago

Tu ne peux pas les différencier de façon fiable avec le BEN_RNG_GEM car le BEN_RNG_GEM peut changer en cas de changement de régime. Le BEN_RNG_GEM n'a pas le même sens selon les régimes.

Je crois qu'on a 2 discussion en parallèle :