### EMOIS 2026 - atelier PMSI avec R, Python, SQL, perspectives sur les fichiers parquet
*sur LibreDataHub*
<br>
<hr>
###### Guillaume Pressiat & Lucas Bourneuf - CHU de Brest
###### Adrien Parrot & Antoine Lamer - InterHop.org
###### Raphaël Simon & Vincent Biot - ATIH
---
## InterHop.org
- Pour des communs numériques en santé
- Transparence et partage libre / décentralisé des savoirs en informatique médicale
- Protection de la vie privée et préservation du secret médical (Serment d'Hippocrate)
----
## InterHop.org/nous
Professionnel·les de santé, ingénieur·es, datascientists, juriste, DPO
----
## Datathon
L'association organise des hackathons sur données
interhop.org/projets/datathon
<hr>
#### Objectifs
- Aide aux développements d'algorithmes
- Réutilisation locale dans les centres de soins
- Se rencontrer et travailler ensemble :-)
----
## Outils proposés par InterHop
[Bitwarden](https://interhop.org/projets/bitwarden)
[Element](https://interhop.org/projets/element)
[Goupile](https://interhop.org/projets/goupile)
[Rekkord](https://rekkord.org)
[LinkR](https://interhop.org/projets/linkr)
[LibreDataHub](https://home.libredatahub.org)
----
### [Bitwarden](https://password.interhop.org/)

----
### [Goupile](https://goupile.hds.interhop.org/)

https://pubmed.ncbi.nlm.nih.gov/35612138/
----
### [Cryptpad](https://cryptpad.hds.interhop.org/)

----
### [LibreDataHub](https://libredatahub.org)

----
### [LinkR](https://linkr.interhop.org)

https://authors.elsevier.com/a/1kovW4xGJ-GTlY
---
### Inscription sur SSO InterHop
Via le SSO Keycloak
keycloak.interhop.org/realms/Interhop/account

----
### Connexion à LibreDataHub
home.libredatahub.org
Dans le cadre de cet atelier, on utilisera des comptes génériques de formation
que nous vous avons communiqué en tout début d'atelier
----
## Programme de l'atelier
- Lire les données PMSI au format in/out avec R et Python
- réaliser des traitements sur ces données
- les réexporter au format parquet dans l'objectif d'alimenter un lac de données
- thématique métier : séjours pour pose de prothèse de hanche
----
## Les outils de l'atelier
- R : les packages [pmeasyr](https://github.com/GuillaumePressiat/pmeasyr), [nomensland](https://github.com/GuillaumePressiat/nomensland), dplyr et arrow
- Python : les packages [pypmsi](https://github.com/GuillaumePressiat/pypmsi) et [refpymsi](https://github.com/GuillaumePressiat/refpymsi), polars
- fichiers parquet : écriture avec le package arrow
- lac de données : requêtage avec duckdb
- requêtage sur le stockage s3 InterHop
----
## Les données de l'atelier
### Base école ATIH
- Des fichiers .rsa ont été générés, avec des données issues de
- La base école ATIH 2022 et 2023
- Merci à Raphaël Simon, Vincent Biot et Matthieu Mercier (ATIH) !
---
## parquet ?
à lire : https://dridk.me/parquet-files.html

----
## parquet : en quelques mots
- Un format libre et open source, indépendant du langage
- Plus de problèmes de typage (date, char, int, etc.) à la lecture (csv, txt, ...)
- Format en colonnes : plutôt que par ligne, économie de stockage, accélère l'exécution des requêtes (OLAP)
- Compression et décompression des données efficaces
[source](https://www.databricks.com/fr/blog/what-is-parquet)
----
## arrow ?

----
## parquet + arrow = le top
---
## Maintenant, codons ensemble !
----
## PMSI et parquet avec R
On travaillera dans RStudio@libredatahub
Pour copier / coller du code, c'est [ici](https://github.com/GuillaumePressiat/emois-2026/blob/main/prepare-atelier/lake_with_duckdb.R)
----
### R / Lire les données
<style>
.slides pre {
text-align: left;
display: flex;
justify-content: center;
}
</style>
```r
library(pmeasyr)
library(dplyr, warn.conflicts = FALSE)
library(arrow)
rsa <- irsa(finess = 'EMOIS2026',
annee = 2023,
mois = 12,
path = 'public/base_ecole_atih',
typi = 6) %>%
tdiag()
```
----
### R / écrire les fichiers parquet
exemple 1 : un seul fichier parquet
```r
rsa$rsa %>% arrow::write_dataset(
'r_lake/mco_rsa.parquet'
)
```
----
### R / écrire les fichiers parquet
exemple 2 : partition de fichiers parquet
```r
rsa$rsa %>% arrow::write_dataset(
'r_lake/mco_rsa',
partitioning = c('ANSOR', 'MOISSOR')
)
```
----
### R / requêter les données avec duckdb
```r
library(duckdb)
drv <- duckdb()
con <- dbConnect(drv)
dbExecute(con, "
--INSTALL httpfs;
LOAD httpfs")
dbGetQuery(con, "
select count(*) from read_parquet('r_lake/mco_rsa/*/*/*.parquet',
hive_partitioning = true) where RSATYPE = 'C'
")
```
----
### R / créer une vue dans duckdb
```r
dbExecute(con, "
create or replace view mco_rsa as
select * from read_parquet('r_lake/mco_rsa/*/*/*.parquet',
hive_partitioning = true)")
```
---
## PMSI et parquet avec Python
On travaillera dans JupyterLab@libredatahub
Pour copier / coller du code, c'est [ici](https://github.com/GuillaumePressiat/emois-2026/blob/main/prepare-atelier/lake_with_duckdb_polars.ipynb)
```python
import polars as pl
import pypmsi as pm
import duckdb
p = pm.noyau_pmsi(finess = 'EMOIS2026',
annee = 2023,
mois = 12,
path = 'public/base_ecole_atih')
rsa = p.irsa()
```
----
### Python / écrire les fichiers parquet
exemple 1 : un seul fichier parquet
```python
(
rsa['rsa']
.write_parquet('python_lake/mco_rsa.parquet')
)
```
----
### Python / écrire les fichiers parquet
exemple 2 : partition de fichiers parquet
```r
(
rsa['rsa']
.write_parquet('python_lake/mco_rsa',
partition_by=['ansor', 'moissor'])
)
```
----
### Python / requêter les données avec duckdb
```python
duckdb.sql("""
select count(*) from
read_parquet(
'python_lake/mco_rsa/*/*/*.parquet',
hive_partitioning = true)
where RSATYPE = 'C'
""")
```
----
### Python / créer une vue dans duckdb
```python
duckdb.sql(
"""
create or replace view mco_rsa as
select * from read_parquet('python_lake/mco_rsa/*/*/*.parquet',
hive_partitioning = true)
""")
```
---
## PMSI et parquet avec SQL
Ouvrir cbeaver pour écrire du SQL
----
## Requêtes des parquets précédents avec duckdb
- ouvrir une nouvelle connexion duckdb
- installer l'extension httfs, la charger
```sql
SELECT ansor, moissor, count(*) FROM
read_parquet('**/pub_lake/mco_actes/*/*/*.parquet',
hive_partitioning = true)
group by ansor, moissor;
SELECT ansor, moissor, count(*) FROM
read_parquet('**/pub_lake/mco_actes/*/*/*.parquet',
hive_partitioning = true)
were regexp_matches(acte, 'N.KA')
group by ansor, moissor;
```
----
## Requêtage s3 interhop
----
## Définitions
- S3 : **s**imple **s**torage **s**ervice
- bucket : grand répertoire contenant des fichiers, conteneur principal
- path : chemin vers des fichiers / objets
- partition : ensemble de fichiers homogènes
(même tables explosées en plusieurs fichiers)
**exemples :**
```
s3://bucket/path/fichier
s3://bucket/path/partition/fichier
```
----
## `glob` : lister les objets S3
```sql
-- listing de tous les objets sur le s3
SELECT *
FROM glob('s3://interhop-pmsi-tuto/**');
-- listing de tous les objets sur le s3 affichés sans l'extension parquet
SELECT distinct regexp_replace(file, '/data_[0-9].parquet', '')
FROM glob('s3://interhop-pmsi-tuto/**');
```
On distingue différents types de stockage :
- sans partitionnement
- partitionnement hive : *`annee=2026/mois=03`*
----
## Requêtes des objets S3
Ici, on requête la partie `fixe` des RSA base école ATIH.
```sql
-- pas de partition, deux années fixe séparées
select count(*), annee
from
read_parquet('s3://interhop-pmsi-tuto/*/fixe.parquet')
group by annee;
-- partition hive, deux années fixe rangées dans annee=202x
select annee, count(*)
from
read_parquet('s3://interhop-pmsi-tuto/hive_style/fixe/*/*.parquet')
group by annee;
```
----
## Requêtes des objets S3 InterHop
Ici, on fait une grosse jointure entre `fixe` et `acte`
```sql
select f.annee, a.acte, count(*) as nb
from
read_parquet('s3://interhop-pmsi-tuto/hive_style/fixe/*/*.parquet') f
inner join read_parquet('s3://interhop-pmsi-tuto/hive_style/acte/*/*.parquet') a
on f.ident = a.ident
and f.annee = a.annee
where regexp_matches(a.acte, 'N.KA')
group by f.annee, a.acte
order by nb desc
```
----
## Bonnes pratiques
- organiser, ranger les fichiers en pensant aux pouvoirs de `glob`
- garder une logique stable au fil du temps
- penser que l'on peut réorganiser, mais que cela a un coût (temps, risque d'erreurs)
---
## [pmsi-io](https://github.com/GuillaumePressiat/pmsi-io/)
<img src="https://guillaumepressiat.github.io/images/pmsi-io-2.png" alt="pmsi-io" width="700"/>
---
## Ouverture : parquet et ATIH
Et si un jour nous avions des fichiers parquet en sortie des logiciels de l'ATIH (Druides) ?
{"type":"slide","tags":"interhop, ppt, emois, 2026","slideOptions":{"transition":"slide"}}