Tutoriel - Usage de la Base sur la Qualité et la Sécurité des Soins (BQSS)#

Ce notebook vise à montrer un usage type dont peut être l’objet BQSS, de façon programmatique grâce au langage Python.

Import des librairies et des données#

Les URLS des données sont récupérable sur la page de la Base sur la Qualité et la Sécurité des Soins sur la plateforme Data Gouv accessible via ce lien. La section Fichiers contient les données disponibles, et pour chaque fichier, une description est présente incluant notamment un URL stable qu’il est recommandé d’utiliser.

La base BQSS adoptant un format clé-valeurs, il est nécessaire de récupérer la table des valeurs d’intérêts (concernant la qualité et la sécurité des soins) ainsi que les métadonnées associées spécifiant ces valeurs et les données caractérisant les établissements de santé via les numéro FINESS.

import numpy as np
import pandas as pd  # version >= 1.4.2

# chargement du fichier valeurs.csv dans un dataframe pandas
valeurs_df = pd.read_csv(
    "https://www.data.gouv.fr/fr/datasets/r/da295ccc-2011-4995-b810-ad1f1a82a83f",
    low_memory=False,
)

# chargement du fichier metadata.csv dans un dataframe pandas
metadata_df = pd.read_csv(
    "https://www.data.gouv.fr/fr/datasets/r/e56fb5a5-5a74-4507-ba77-e0411d4aa234",
    low_memory=False,
)

# chargement du fichier finess.csv dans un dataframe pandas
finess_df = pd.read_csv(
    "https://www.data.gouv.fr/fr/datasets/r/48dadbce-56a8-4dc4-ac51-befcdfd82521",
    low_memory=False,
)

Observation des données#

Il est désormais possible de consulter les informations caractérisant ces données et en observer un échantillon.

Caractérisation des données valeurs_df#

valeurs_df.info()
valeurs_df.sample(n=5, random_state=187)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1432745 entries, 0 to 1432744
Data columns (total 10 columns):
 #   Column         Non-Null Count    Dtype  
---  ------         --------------    -----  
 0   annee          1432745 non-null  int64  
 1   finess         1432745 non-null  object 
 2   finess_type    1432745 non-null  object 
 3   key            1432745 non-null  object 
 4   value_boolean  608398 non-null   object 
 5   value_string   110483 non-null   object 
 6   value_integer  227845 non-null   float64
 7   value_float    340421 non-null   float64
 8   missing_value  136469 non-null   object 
 9   value_date     9129 non-null     object 
dtypes: float64(2), int64(1), object(7)
memory usage: 109.3+ MB
annee finess finess_type key value_boolean value_string value_integer value_float missing_value value_date
1429044 2020 210013447 geo sld True NaN NaN NaN NaN NaN
80324 2017 950300202 geo filtre_heb_ssr False NaN NaN NaN NaN NaN
37018 2019 260000146 geo filtre_heb_perinat False NaN NaN NaN NaN NaN
869559 2016 050002948 jur mco_hpp_del1_2016-del1_c1_pos_seuil_etbt NaN C NaN NaN NaN NaN
647469 2019 920000643 geo perinat_sejces_dm NaN NaN NaN 5.8 NaN NaN

Un grand nombre de variables de nature différente sont regroupées dans cette table (d’où la table metadata venant spécifier la nature de chaque variables). Le nom des variables est stocké dans la colonne key.

Afin de pouvoir distinguer les différents types de valeurs (booléen, entier, décimal, chaîne de caractères, valeurs manquantes, dates), des colonnes dédiées leur sont attachées.

Ainsi, pour une variable donnée, un seul type est possible… :

  • sur l’ensemble de la classe (hormis la colonne missing_value)

  • pour chaque valeur (justifiant la nature lacunaire de ces colonnes, toutes les colonnes autre que celle prenant la valeur étant à NaN)

Caractérisation des données metadata_df#

metadata_df.info()
metadata_df.sample(n=5, random_state=123)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 653 entries, 0 to 652
Data columns (total 16 columns):
 #   Column             Non-Null Count  Dtype  
---  ------             --------------  -----  
 0   name               653 non-null    object 
 1   title              653 non-null    object 
 2   description        259 non-null    object 
 3   type               652 non-null    object 
 4   source             653 non-null    object 
 5   indicateur         474 non-null    object 
 6   secteur            547 non-null    object 
 7   theme              474 non-null    object 
 8   acronyme           436 non-null    object 
 9   version            440 non-null    float64
 10  variable           440 non-null    object 
 11  annee              440 non-null    float64
 12  ancienne_variable  440 non-null    object 
 13  url_rapport        436 non-null    object 
 14  type_metier        589 non-null    object 
 15  finess_type        653 non-null    object 
dtypes: float64(2), object(14)
memory usage: 81.8+ KB
name title description type source indicateur secteur theme acronyme version variable annee ancienne_variable url_rapport type_metier finess_type
381 mco_dan_tda_2015-tda_c_etbt Valeur tenue du dossier anesthésique NaN classe IQSS dossier patient MCO_DAN_TDA_2015 MCO DAN TDA 2015.0 tda_c_etbt 2015.0 tda_c_etbt https://www.has-sante.fr/upload/docs/applicati... resultat mixte
275 mco_isoortho_ptg_2020-iso_ptg_evol Evolution du statut des établissements évalués... NaN float-string IQSS PMSI MCO_ISOORTHO_PTG_2020 MCO ISOORTHO PTG 2020.0 iso_ptg_evol 2020.0 iso_ptg_evol https://www.has-sante.fr/upload/docs/applicati... evolution geo
43 certification_ref_2021_score_objectif_2.1 Objectif 2.1 : La pertinence des parcours, des... NaN float Certification v2021 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN geo
227 mco_avc_epr1_2014-epr1_c1_ichaut_etbt Intervalle de confiance haut de l'évaluation p... NaN int IQSS dossier patient MCO_AVC_EPR1_2014 MCO AVC EPR1 2014.0 epr1_c1_ichaut_etbt 2014.0 epr1_c1_ichaut_etbt https://www.has-sante.fr/upload/docs/applicati... intervalle_haut mixte
356 mco_dia_ser_2014-ser_c_den_etbt Dénominateur surveillance sérologique des hépa... NaN float IQSS dossier patient MCO_DIA_SER_2014 MCO DIA SER 2014.0 ser_c_den_etbt 2014.0 ser_c_den_etbt https://www.has-sante.fr/upload/docs/applicati... denominateur mixte

La colonne name de cette table permet de faire la jointure avec la table valeurs_df via la colonne key associée.

Les métadonnées permettent de compléter les informations associées aux variables, en particulier leur type (encodé implicitement dans valeur.csv, voir ci-dessus), leur source (provenant d’origines variées), leur secteur, leur theme et leur acronyme.

Pour une recherche rapide, vous pouvez aussi utiliser directement le fichier metadata.xlsx qui permet de faire des filtres rapides sur les différentes colonnes.

Caractérisation des données finess_df#

finess_df.info()
finess_df.sample(n=5, random_state=123)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 165374 entries, 0 to 165373
Data columns (total 56 columns):
 #   Column                        Non-Null Count   Dtype  
---  ------                        --------------   -----  
 0   date_export                   165374 non-null  object 
 1   num_finess_et                 165374 non-null  object 
 2   num_finess_ej                 165374 non-null  object 
 3   raison_sociale_et             165374 non-null  object 
 4   raison_sociale_longue_et      116991 non-null  object 
 5   complement_raison_sociale     21061 non-null   object 
 6   complement_distribution       25820 non-null   object 
 7   num_voie                      124493 non-null  object 
 8   type_voie                     154310 non-null  object 
 9   libelle_voie                  158756 non-null  object 
 10  complement_voie               4965 non-null    object 
 11  lieu_dit_bp                   28910 non-null   object 
 12  commune                       8907 non-null    float64
 13  departement                   165374 non-null  object 
 14  libelle_departement           165374 non-null  object 
 15  ligne_acheminement            165374 non-null  object 
 16  telephone                     146183 non-null  object 
 17  telecopie                     93832 non-null   object 
 18  categorie_et                  165374 non-null  int64  
 19  libelle_categorie_et          165374 non-null  object 
 20  categorie_agregat_et          165374 non-null  int64  
 21  libelle_categorie_agregat_et  165374 non-null  object 
 22  siret                         137639 non-null  float64
 23  code_ape                      73828 non-null   object 
 24  code_mft                      165374 non-null  int64  
 25  libelle_mft                   165374 non-null  object 
 26  code_sph                      164361 non-null  float64
 27  libelle_sph                   164361 non-null  object 
 28  date_ouverture                165374 non-null  object 
 29  date_autorisation             165374 non-null  object 
 30  date_maj                      165374 non-null  object 
 31  num_uai                       2329 non-null    object 
 32  coord_x_et                    98237 non-null   float64
 33  coord_y_et                    98235 non-null   float64
 34  source_coord_et               97922 non-null   object 
 35  date_geocodage                100664 non-null  object 
 36  region                        156467 non-null  float64
 37  libelle_region                156467 non-null  object 
 38  code_officiel_geo             156467 non-null  object 
 39  code_postal                   165374 non-null  int64  
 40  libelle_routage               156467 non-null  object 
 41  libelle_code_ape              67887 non-null   object 
 42  ferme_cette_annee             165374 non-null  bool   
 43  latitude                      97908 non-null   float64
 44  longitude                     97908 non-null   float64
 45  libelle_commune               165374 non-null  object 
 46  adresse_postale_ligne_1       122943 non-null  object 
 47  adresse_postale_ligne_2       165374 non-null  object 
 48  raison_sociale_ej             165374 non-null  object 
 49  raison_sociale_longue_ej      130887 non-null  object 
 50  statut_juridique_ej           165374 non-null  int64  
 51  libelle_statut_juridique_ej   165374 non-null  object 
 52  statut_juridique              165374 non-null  object 
 53  type_etablissement            165374 non-null  object 
 54  actif_qualiscope              165374 non-null  bool   
 55  dernier_enregistrement        165374 non-null  bool   
dtypes: bool(3), float64(8), int64(5), object(40)
memory usage: 67.3+ MB
date_export num_finess_et num_finess_ej raison_sociale_et raison_sociale_longue_et complement_raison_sociale complement_distribution num_voie type_voie libelle_voie ... adresse_postale_ligne_1 adresse_postale_ligne_2 raison_sociale_ej raison_sociale_longue_ej statut_juridique_ej libelle_statut_juridique_ej statut_juridique type_etablissement actif_qualiscope dernier_enregistrement
1404 2022-07-08 210983565 210012142 CH - HCO USLD MONTBARD CH - HCO USLD MONTBARD CH - HCO USLD MONTBARD NaN 24 Rue AUGUSTE CARRE ... 24 Rue Auguste Carre 21500 MONTBARD CTRE HOSPITALIER DE LA HAUTE COTE D OR CENTRE HOSPITALIER DE LA HAUTE CÔTE-D'OR 14 Etablissement Public Intercommunal d'Hospitali... Public Public True True
80171 2006-12-31 810102947 810000471 ANTENNE D'AUTODIALYSE LESCURE ANTENNE D'AUTODIALYSE LESCURE D'ALBIGEOIS NaN NaN NaN Impasse LARQUIPEYRE ... NaN 81380 LESCURE D ALBIGEOIS SA CLINIQUE CLAUDE BERNARD SA CLINIQUE CLAUDE BERNARD 73 Société Anonyme Privé Privé False False
17438 2017-12-31 520004094 520003781 POLE CANCERO SUD HTE MARNE CMC CHAUMON NaN NaN NaN 17 Avenue DES ETATS UNIS ... 17 Avenue Des Etats Unis 52001 CHAUMONT CEDEX GCS POLE DE CANCERO DU SUD HAUT MARNAI NaN 29 G.C.S. public Public Public False False
109866 2009-12-31 780824033 780001236 CENTRE MEDICO-PSY SECT.78-I-2 CENTRE MEDICO-PSYCHOLOGIQUE SECTEUR 78-I-2 NaN NaN 1 Rue CHARLES BOURSEUL ... 1 Rue Charles Bourseul 78700 CONFLANS STE HONORINE CH INTERCOM DE POISSY ST-GERMAIN CENTRE HOSPITALIER INTERCOMMUNAL POISSY ST-GER... 14 Etb.Pub.Intcom.Hosp. Public Public False False
291 2022-07-08 060019957 060780988 CMP ADULTE SECT3 CH CANNES CMP ADULTE SECT3 CH CANNES PSYCHIATRIE ADULTE NaN 27 Avenue ISOLA BELLA ... 27 Avenue Isola Bella 06400 CANNES CH DE CANNES SIMONE VEIL CENTRE HOSPITALIER DE CANNES SIMONE VEIL 13 Etablissement Public Communal d'Hospitalisation Public Public False True

5 rows × 56 columns

Cette table contient l’ensemble des données Finess historisées. Il y a une ligne par export et par Finess présent à la date de l’export. Pour un même Finess il ya donc très souvent plusieurs lignes.

Les colonnes qui s’avèrent souvent utiles sont:

  • num_finess_et: numéro finess géographique

  • num_finess_ej: numéro finess juridique

  • latitude et longitude: les coordonnées géographiques de l’établissement dans le référentiel WGS84

  • raison_sociale_et: le nom de l’établissement

  • dernier_enregistrement: indique si cette ligne est la dernière connue pour le finess en question

Préparation des données#

Récupération des clés associées à des catégories de valeurs#

Les cas d’usages pour lesquels la base est utilisé ne concernent souvant qu’un sous-ensemble des domaines présents dans la base. On peut par exemple vouloir récupérer l’historique complet des IQSS issus du questionnaire patient (ESATIS).

La mécanique pour sélectionner le sous ensemble de données d’interêt est la suivante:

  • Dans le fichier metadata.csv utiliser la colonne source pour identifier le domaine d’intérêt

  • Dans le fichier metadata.csv recupérer le nom des variables de la source donnée qui sont stockées dans la colonne name

  • Parmis ces variables, utiliser les colonne type_metier (pour les IQSS) et/ou description pour sélectionner les variables d’intérêt

  • Dans le fichier valeurs.csv sélection toutes les lignes dont la colonne key contient une variable du domaine d’intérêt

Ci-dessous un exemple de cette mécanique:

# Affichage des sources de données existantes
metadata_df["source"].value_counts()
IQSS dossier patient                403
SAE                                 115
IQSS questionnaire patient           34
Certification v2014                  33
IQSS PMSI                            22
Certification v2021                  21
IQSS questionnaire établissement     15
Activités ET                         10
Name: source, dtype: int64
# Récupération des noms des variables de certification v2014
certif_14_keys = metadata_df[metadata_df["source"] == "Certification v2014"][
    "name"
]

# Récupération des nom des variables esatis
esatis_keys = metadata_df[
    metadata_df["source"] == "IQSS questionnaire patient"
]["name"]
# Affichage des types métiers certification
# Les variables de certification n'ont pas de type métier
metadata_df.loc[
    metadata_df["name"].isin(certif_14_keys),
    ["name", "description", "type_metier"],
].head(5)
name description type_metier
0 certif_V2014_id_niveau Code du niveau de certification validé par le ... NaN
1 certif_date Date de délibération du collège de la HAS qui ... NaN
2 certif_V2014_id_demarche Code interne à la HAS.\nIl s’agit d’un code pe... NaN
3 certif_V2014_decision_thematique_1 Décision finale pour la thématique : Managemen... NaN
4 certif_V2014_decision_thematique_2 Décision finale pour la thématique : Qualité d... NaN
# Affichage des types métiers esatis
metadata_df.loc[
    metadata_df["name"].isin(esatis_keys),
    ["name", "description", "type_metier"],
].head(5)
name description type_metier
494 nb_rep_score_all_rea_ajust Nombre de réponses concernant la satisfaction ... effectif_observe
495 score_all_rea_ajust Note ajustée de satisfaction globale classemen... score
496 classement_48h Classement en 6 classes {A: >=77.3, B: [74-77.... classe
497 evolution_48h Changement de classe d'une année à l'autre evolution
498 nb_rep_score_accueil_rea_ajust Nombre de réponses concernant la satisfaction ... effectif_observe
# Affichage des variables de type score pour esatis
metadata_df.loc[
    metadata_df["name"].isin(esatis_keys)
    & (metadata_df["type_metier"] == "score"),
    ["name", "description", "type_metier"],
]
name description type_metier
495 score_all_rea_ajust Note ajustée de satisfaction globale classemen... score
499 score_accueil_rea_ajust Note ajustée concernant la satisfaction de l'a... score
501 score_pecinf_rea_ajust Note ajustée de satisfaction de la prise en ch... score
503 score_pecmed_rea_ajust Note ajustée de satisfaction de la prise en ch... score
505 score_chambre_rea_ajust Note ajustée de satisfaction de la chambre score
507 score_repas_rea_ajust Note ajustée de satisfaction des repas score
509 score_sortie_rea_ajust Note ajustée de satisfaction de la sortie score
510 taux_reco_brut_48h Pourcentage de patients recommandant certainem... score
513 score_all_ajust_ca Score de satisfaction globale ajusté score
516 score_avh_ajust Note ajustée de la satisfaction avant l’hospit... score
518 score_acc_ajust Note ajustée concernant la satisfaction accuei... score
520 score_pec_ajust Note ajustée de la satisfaction de la prise en... score
522 score_cer_ajust Note ajustée de la satisfaction chambre et rep... score
524 score_ovs_ajust Note ajustée de la satisfaction sortie et reto... score
526 taux_reco_brut_ca Pourcentage de patients recommandant certainem... score

Isolation des domaines de données#

Afin de pouvoir préparer et analyser un domaine de données, il est nécessaire de l’isoler en vue de traitements décrits plus bas. Pour des raisons de volumétrie, le présent tutoriel se restreint aux données esatis. Mais il est naturellement possible d’effectuer ces analyses sur un ensemble de domaines de données, voire sur tous les domaines (les mêmes opérations décrites ici peuvent leur être appliquées).

# Isolation du domaine de données esatis
esatis_df = valeurs_df[valeurs_df["key"].isin(esatis_keys)]

# Isolation du domaine de données certification v2014, pour illustration
certif_df = valeurs_df[valeurs_df["key"].isin(certif_14_keys)]

Pivot de la table esatis#

Actuellement, le format clé-valeur de la base induit que chaque valeur de chaque variable pour chacun des établissements est associée à une ligne. Nous souhaitons pourvoir avoir un regroupement des valeurs pour chaque établissement.

Pour cela, nous devons effectuer les opérations suivantes (cf. cellule de code ci-dessous) :

  • Effectuer un pivot à la table pour avoir une colonne par variable (par type), chaque ligne représentant un établissement pour une année donnée (puisque certaines valeurs sont collectées annuellement)

  • Chaque classe de valeur n’ayant qu’un type de valeur acceptable (hormis le type missing_value), toutes les colonnes des autres types seront remplis de NaN => il s’agit donc également de supprimer ces colonnes inutiles

  • Les colonnes des valeurs manquantes pour une clé sont fusionnées avec la colonne de valeurs de la clé correspondante pour ne pas perdre l’information correspondante

# Les colonnes de valeurs sont pivotées selon le colonne key, pour chaque triplet (annee, finess, finess_type)
esatis_df = esatis_df.pivot(
    index=["annee", "finess", "finess_type"], columns="key"
)

# Toutes les colonnes de valeurs liées à un type incorrect vis-à-vis du type attendu sont remplies par des NaN.
# Il s'agit ici de supprimer ces colonnes qui ne portent aucune information exploitable
esatis_df = esatis_df.dropna(axis=1, how="all")

# Les colonnes associées au type missing_value sont fusionnées avec leur colonne de valeur respective
# Cette étape est optionnelle si les valeurs manquantes sont sans intérêts pour l'étude
if "missing_value" in esatis_df:
    esatis_df = esatis_df.combine_first(esatis_df["missing_value"]).drop(
        columns="missing_value"
    )

# Les colonnes qui résultent de ces opérations ont plusieurs niveaux qui sont ici applatis pour n'en avoir plus qu'un
esatis_df = esatis_df.droplevel(0, axis=1)
# Les données d'années, de finess et de finess_type utilisées jusqu'ici comme index sont basculées en colonnes dans la table.
esatis_df = esatis_df.reset_index()

Un échantillon de la table résultante peut être observée ci-dessous, en notant qu’il manque des données pour de nombreux établissements sur certaines années car certains indicateurs n’étaient pas calculés à ce moment là.

esatis_df.sample(n=5, random_state=123)
key annee finess finess_type classement_48h classement_ca evolution_48h evolution_ca nb_reco_brut_48h nb_reco_brut_ca nb_rep_score_acc_ajust ... score_cer_ajust score_chambre_rea_ajust score_ovs_ajust score_pec_ajust score_pecinf_rea_ajust score_pecmed_rea_ajust score_repas_rea_ajust score_sortie_rea_ajust taux_reco_brut_48h taux_reco_brut_ca
607 2016 590790655 geo Données insuffisantes NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3852 2019 370000531 geo B NaN 3-Amélioration NaN 94.0 NaN NaN ... NaN 75.21 NaN NaN 84.50 80.37 60.41 64.52 71.3 NaN
1975 2017 750000549 geo B NaN 3-Amélioration NaN NaN NaN NaN ... NaN 72.54 NaN NaN 80.98 82.22 62.58 64.17 NaN NaN
1074 2016 930000302 geo Données insuffisantes NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
879 2016 760805770 geo D NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 37 columns

Exploitation des données#

Dans cette section, une analyse simple sur le domaine esatis est effectuée à des fins d’illustration quant à la valorisation de ces données.

Le cas d’usage de cette analyse est l’observation de l’évolution du positionnement national d’un établissement identifié (il s’agit ici de l’établissement associé au finess n°060000478) vis-à-vis des établissements de même catégorie (il s’agit ici de la catégorie Centres Hospitaliers, associée au code 1102) sur l’indicateur score_all_ajust_ca (correspondant au “score de satisfaction globale ajusté” en chirurgie ambulatoire).

Pour ce faire, il faut :

  • associer aux données esatis les données finess nécessaires à la jointure et à la catégorisation des établissements

  • calculer le classement de l’établissement (son rang absolu et le pourcentage associé) pour chaque année

  • représenter la distribution des établissements pour chaque année en positionnant l’établissement étudié

Ces étapes sont réalisées dans les deux sections ci-dessous.

Finalisation de la préparation des données#

# On ne prend que les informations des finess les plus récentes pour éviter les doublons à la jointure
finess_df = finess_df.loc[finess_df["dernier_enregistrement"]]

# Jointure entre les données esatis et les données Finess restreintes aux agrégats de catégories d'établissement
df = finess_df[
    [
        "num_finess_et",
        "categorie_agregat_et",
        "raison_sociale_et",
        "departement",
    ]
].merge(esatis_df, left_on="num_finess_et", right_on="finess", how="inner")
df.sample(5, random_state=123)
num_finess_et categorie_agregat_et raison_sociale_et departement annee finess finess_type classement_48h classement_ca evolution_48h ... score_cer_ajust score_chambre_rea_ajust score_ovs_ajust score_pec_ajust score_pecinf_rea_ajust score_pecmed_rea_ajust score_repas_rea_ajust score_sortie_rea_ajust taux_reco_brut_48h taux_reco_brut_ca
607 130783293 1101 APHM HOPITAL LA TIMONE 13 2016 130783293 geo Données insuffisantes NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3852 620100750 1110 CLINIQUE AMBROISE PARE 62 2017 620100750 geo B NaN 2-Stable ... NaN 77.67 NaN NaN 82.97 82.36 61.93 66.11 NaN NaN
1975 340780725 1110 CL VIA DOMITIA 34 2020 340780725 geo B B NaN ... 74.48 75.96 70.87 85.01 83.56 82.84 48.60 65.61 67.6 71.6
1074 220000368 1102 CENTRE HOSPITALIER LANNION 22 2017 220000368 geo C NaN 2-Stable ... NaN 68.88 NaN NaN 82.26 79.18 64.03 61.99 NaN NaN
879 170000095 1102 CENTRE HOSPITALIER ST-JEAN D'ANGELY 17 2018 170000095 geo Données insuffisantes Données insuffisantes 4-Non calculable ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 41 columns

# Seuls les centres hospitaliers sont conservés
df = df[df["categorie_agregat_et"] == 1102]

# Pour cette étude, seules les colonnes suivantes sont nécessaires pour la suite : annee, taux_reco_brut_ca, finess
# Par ailleurs, cet indicateur n'est collecté qu'a partir de 2019.
df = df.loc[
    df["annee"] >= 2019,
    [
        "annee",
        "finess",
        "raison_sociale_et",
        "departement",
        "score_all_ajust_ca",
    ],
]

# Les établissements sans valeurs pour l'indicateur sont retirés
df = df.dropna()

Un extrait de la table correspondante peut être observée :

df.sample(5, random_state=123)
annee finess raison_sociale_et departement score_all_ajust_ca
6339 2021 930000286 GHI LE RAINCY MONTFERMEIL 93 75.89
3104 2019 550000012 CH VERDUN/ST MIHIEL-HOP ST NICOLAS 55 76.95
4587 2021 710978263 CH WILLIAM MOREY CHALON SUR SAONE 71 80.67
3764 2019 620000034 CH ARRAS 62 77.77
3328 2021 580972693 HOPITAL PIERRE BEREGOVOY 58 72.74

Visualisation des résultats#

es_finess = "060000478"
axes = df.plot.hist(by="annee", bins=20, figsize=(10, 15), legend=False)
for i, annee in enumerate(np.sort(df["annee"].unique())):
    axes[i].set_xlim(0, 100)
    axes[i].set_ylim(0, 37)
    axes[i].set_ylabel("Fréquences", fontsize=12)
    df_tmp = (
        df[df["annee"] == annee]
        .sort_values("score_all_ajust_ca", ascending=False)
        .reset_index()
    )
    value = df_tmp.loc[
        df_tmp["finess"] == es_finess, "score_all_ajust_ca"
    ].values[0]
    axes[i].axvline(value, color="red")
    axes[i].text(value - 3.2, -4.5, str(value), color="red", fontsize=12)
    axes[i].text(
        value + 1, 38, "finess n°" + str(es_finess), color="red", fontsize=12
    )
    rank = df_tmp[df_tmp["finess"] == es_finess].index.item() + 1
    card_finess = df_tmp.shape[0]
    rank_ratio = 100 * rank / card_finess
    axes[i].text(
        5,
        30,
        f"classement : {rank} / {card_finess}\nposition (%) : {rank_ratio:,.1f}",
        backgroundcolor="lightgrey",
        color="red",
        fontsize=12,
        fontweight="roman",
    )
axes[2].set_xlabel(
    "score de satisfaction globale ajusté",
    fontsize=12,
    labelpad=15,
)
Text(0.5, 0, 'score de satisfaction globale ajusté')
../../_images/3c57ed145ca868882e6d54a2274a65e91188f4399796b32c6bea86de1ace083c.png

⚠️ Attention : L’analyse et l’interprétation des résultats des IQSS nécessite de bien prendre connaissance de leur définition.

Nous pouvons constater que l’établissement considéré dans cette étude a:

  • Amélioré son score (de 77.73 à 80.78)

  • Amélioré sa place dans la distribution de 54.6ème percentile à 24.3ème percentile