Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposition d'ajout sur les fichiers parquet #523

Merged
merged 3 commits into from
Apr 26, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion 03_Fiches_thematiques/Fiche_import_fichiers_parquet.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ Le format Parquet présente trois caractéristiques importantes du point de l'ut
knitr::include_graphics("../pics/parquet/stockage_colonne.png")
```

- **Un fichier Parquet contient à la fois les données et des métadonnées**. Ces métadonnées écrites à la fin du fichier enregistrent une description du fichier (appelé **schéma**). Ces métadonnées contiennent notamment le type de chaque colonne (entier/réel/caractère). Ce sont ces métadonnées qui font en sorte que la lecture des données Parquet soit optimisée et sans risque d’altération (voir [ici](https://parquet.apache.org/docs/file-format/metadata/) pour en savoir plus).
- **Un fichier Parquet contient à la fois les données et des métadonnées**. Ces métadonnées écrites à la fin du fichier enregistrent une description du fichier (appelé **schéma**). Ces métadonnées contiennent notamment le type de chaque colonne (entier/réel/caractère) et quelques statistiques (min, max). Ce sont ces métadonnées qui font en sorte que la lecture des données Parquet soit optimisée et sans risque d’altération (voir [ici](https://parquet.apache.org/docs/file-format/metadata/) pour en savoir plus).
- **Un fichier Parquet est composé de groupe de lignes (row group)** contenant également des métadonnées similaires à celles du fichier. La taille idéale d'un row group est de l'ordre de 30 000 à 1 000 000.

Dans un contexte analytique, cette organisation des données génère plusieurs avantages dont les principaux sont:

Expand Down Expand Up @@ -131,6 +132,7 @@ Partitionner un fichier revient à le "découper" selon une clé de partitionnem
- **Il est important de bien choisir les variables de partitionnement** d'un fichier **Parquet**. Il faut choisir des variables faciles à comprendre et qui soient cohérentes avec l'usage des données (année, département, secteur...). En effet, un partitionnement bien construit induit par la suite des gains d'efficacité sur les traitements et facilite la maintenance du fichier sur le long terme.
- **Il est inutile de partitionner des données de petite taille**. Si les données dépassent quelques millions d'observations et/ou si leur taille en CSV dépasse quelques giga-octets, il est utile de partitionner.
- **Il ne faut pas partitionner les données en trop de fichiers**. En pratique, il est rare d'avoir besoin de plus d'une ou deux variables de partitionnement.
- **Si vous souhaitez être compatible avec tous les outils lisant du parquet**, il est recommandé de ne pas partitionner sur une variable pouvant être `NA` ou une chaîne vide.
:::

Pour créer des fichiers **Parquet** partitionnés, il faut utiliser la fonction [`write_dataset()`](https://arrow.apache.org/docs/r/reference/write_dataset.html) du _package_ `arrow`. Voici ce que ça donne sur le fichier de la BPE :
Expand All @@ -150,6 +152,50 @@ Avec cette instruction, on a créé autant de répertoires que de modalités dif
knitr::include_graphics("../pics/parquet/fichier_partition.png")
```

### Données volumineuses: optimiser en triant

Il n'est pas toujours possible de partitionner un fichier (variable non discrète ou avec des milliers de modalités...). Dans ces cas là, vous pouvez trier le fichier par la variable à utiliser, cela va permettre une recherche efficace à partir des métadonnées des fichiers et des groupes de lignes.
linogaliana marked this conversation as resolved.
Show resolved Hide resolved

```{r, eval = FALSE}
donnees_BPE |>
arrange(EPCI) |>
write_parquet(
sink = "Data_parquet/BPE_ENS.parquet"
)
```

Vous pouvez bien sûr cumuler les partitions avec des tris :

```{r, eval = FALSE}
donnees_BPE |>
arrange(EPCI) |>
write_dataset(
path = "Data/",
partitioning = c("REG"), # la variable de partitionnement
format="parquet"
)
```

Cette méthode est quasiment aussi efficace que le partitionnement.

### Vérifier qu'un fichier parquet est correctement optimisé

Dans certains cas pathologiques quand vous manipulez de très gros volumes de données (par exemple quand vous partitionnez avec `arrow::open_dataset` un volume de données de plusieurs de dizaine de millions de lignes), le package `arrow` peut générer des fichiers parquet avec un nombre de lignes par row group très petite (inférieur à 1000 voire à 100). Cela rendra toutes les requêtes sur vos fichiers extrèmement lent.

Pour vérifier que vos fichiers ont une taille de row group correcte, vous pouvez utiliser la fonction suivante :

```{r, eval = FALSE}
library(arrow)

mean_row_group_size <- function(path) {
a <- arrow::ParquetFileReader$create(path)
(a$num_rows / a$num_row_groups)
}
mean_row_group_size('bpe2018/REG=11/part-0.parquet')
```

Vous devez obtenir une valeur au moins égale à 10 000. Si vous obtenez une valeur inférieure, vous aurez intérêt à regénérer votre fichier en passant par d'autres méthodes (par exemple générer chaque partition en faisant une boucle et un filtre).

## Lire et exploiter un fichier Parquet avec `R` {#readparquet}

### Cas des données peu volumineuses: importer les données en mémoire
Expand Down