Lors du traitement de DataFrames de grande taille (par exemple, plus de 130 000 lignes de texte et de métadonnées), la fusion efficace des données et leur sauvegarde sous format compressé représente un défi fréquent en ingénierie des données. Ce guide technique décrit une approche complète pour combiner des données à l'aide de Polars et les exporter au format .jsonl.gz en optimisant les performances.
Définition du scénario
- Objectif : Intégrer les étiquettes de sujet (
final_subjects) et les cartographies de probabilité (final_result_map) provenant dedf_subjectdans la table principaledf_text. - Caractéristiques des données : Incluent du texte étendu (
text), des listes (list[str]) et des chaînes structurées au format JSON. - Exigences de sortie : Exporter en format JSON ligneparligne (JSONL) avec une compression Gzip.
Optimisation de la fusion avec l'opération Join
L'opération join de Polars, implémentée en Rust, offre des performances nettement supérieures à celles de Pandas.
import polars as pl
# Approche recommandée : sélectionner les colonnes nécessaires en amont pour éviter les suffixes de noms dupliqués (comme _right)
resultat_fusion = donnees_texte.join(
donnees_matiere.select(["identifiant", "sujets_finaux", "carte_resultats"]),
on="identifiant",
how="left"
)
Remarque : Après la fusion de données massives et fragmentées, il est conseillé d'exécuter resultat_fusion.rechunk(). Cette opération réorganise la mémoire pour rendre les données contiguës, ce qui améliore la vitesse de sérialisation ultérieure.
Problèmes rencontrés avec write_ndjson
En essayant de sauvegarder directement avec compression, plusieurs obstacles apparaisent :
- Paramètre absent : La fonction
write_ndjson()de Polars ne prend pas en charge nativement le paramètrecompression="gzip", contrairement àwrite_csv(). Tenter de l'utiliser génère une erreur de typeTypeError. - Performance limitée de la bibliothèque standard : Utiliser le module Python intégré
gzip(commegzip.open) avec Polars permet de compresser, mais en raison de son exécution monothread et des passes par les E/S Python, le processus devient extrêmement lent. - Impact du niveau de compression : Le module
gzippar défaut utilisecompresslevel=9, ce qui sollicite énormément le CPU et réduit drastiquement la vitesse d'écriture.
Solution performante : intégration de la bibliothèque isal
Pour surmonter les limitations des outils Python standard, il est recommandé d'utiliser la bibliothèque Intel Storage Acceleration Library (ISA-L) via son wrapper Python isal.
Implémentation pratique :
-
Installation :
pip install isal -
Exemple de code : ``` from isal import igzip
def compresser_et_sauvegarder_jsonl(df: pl.DataFrame, chemin_fichier: str): # Utiliser igzip pour une compression à haute vitesse # compresslevel=1 ou 2 offre un excellent compromis entre rapidité et taux de compression with igzip.open(chemin_fichier, "wb", compresslevel=2) as fichier_sortie: df.write_ndjson(fichier_sortie)
Pourquoi isal.igzip surpasse-t-il les autres méthodes ?
- Optimisations matérielles :
isalexploite des instructions assembleur optimisées pour les processeurs modernes (comme les pipelines multiniveaux), atteignant des vitesses 5 à 10 fois supérieures à celles du modulegzipstandard à taux de compression équivalent. - Écriture par flux : La méthode
write_ndjsonde Polars accepte tout objet fichier possédant une méthode.write(). En connectant l'objetigzipà Polars, les données s'écoulent directement de la mémoire vers le moteur de compression, éliminant ainsi la nécessité de fichiers intermédiaires volumineux.
Pistes d'amélioration avancées
- Paramétrage du niveau de compression : Pour les fichiers .jsonl.gz, un
compresslevelentre 1 et 3 représente généralement le meilleur rapport efficacité/coût. Des niveaux plus élevés augmentent de manière exponentielle la charge CPU tout en réduisant marginalement la taille du fichier. - Lecture automatisée : La fonction
read_ndjson()de Polars détecte intelligemment les en-têtes. Ainsi, même pour les fichiers compressés avecisal, l'utilisation depl.read_ndjson("fichier.jsonl.gz")permet une décompression et une lecture automatiques sans intervention supplémentaire. - Format alternatif recommandé : Si l'environnement en aval le permet, le format Parquet (
df.write_parquet(..., compression="zstd")) est le format natif privilégié de Polars, offrant de meilleurs taux de compression et des performances de lecture/écriture supérieures au format JSONL.