Pandas & NumPy Academy · Leçon

Lecture par blocs de fichiers volumineux

Traitez les fichiers qui dépassent la RAM en les lisant par blocs avec chunksize dans read_csv et en agrégeant progressivement les résultats.

Leçon 4 sur 413 étapes

Lecture par blocs de fichiers volumineux est une leçon Pandas & NumPy Academy gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Pandas & NumPy Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Pandas & NumPy Academy comprend 4 leçons au total.

Lorsque les fichiers dépassent la RAM

Dans les pipelines de données utilisés en production, un goulot d’étranglement courant est un fichier CSV plus volumineux que la RAM disponible. Si un fichier fait 20 GB et que la machine dispose de 16 GB de RAM, pd.read_csv('file.csv') échouera avec une MemoryError. La solution consiste à effectuer une lecture par blocs : charger le fichier par morceaux de taille fixe, traiter chaque morceau, puis cumuler les résultats. Vous pouvez ainsi analyser des fichiers de taille arbitraire sans les charger entièrement en mémoire.

import pandas as pd
import numpy as np

# Simulate a large CSV by writing one
np.random.seed(0)
sample = pd.DataFrame({
    'date': pd.date_range('2023-01-01', periods=100000, freq='h'),
    'region': np.random.choice(['North','South','East','West'], 100000),
    'sales': np.random.randint(100, 1000, 100000)
})
sample.to_csv('/tmp/large_sales.csv', index=False)
print(f'File size: {pd.io.common.get_handle("/tmp/large_sales.csv", "r").handle.seek(0, 2)/1e6:.1f} MB... (simulated)')
print('Rows:', len(sample))

Paramètre chunksize de read_csv

Transmettez chunksize=n à pd.read_csv() pour obtenir un itérateur TextFileReader plutôt qu’un DataFrame. Chaque itération fournit les n lignes suivantes sous forme de DataFrame. Ainsi, seules n lignes se trouvent en mémoire à un instant donné. Une bonne valeur de départ pour chunksize est de 100 000 lignes : suffisamment peu pour tenir dans la RAM, mais suffisamment pour limiter les coûts de gestion des entrées-sorties. Ajustez cette valeur en fonction de la RAM disponible et du nombre de colonnes.

import pandas as pd

# Read file in chunks of 25,000 rows
chunk_iter = pd.read_csv('/tmp/large_sales.csv', chunksize=25000)

# Peek at the first chunk
first_chunk = next(chunk_iter)
print('First chunk shape:', first_chunk.shape)
print(first_chunk.head(3))

Parcourir les blocs

Utilisez une boucle for sur l’itérateur de blocs pour traiter chaque bloc. Pour les opérations simples, comme compter les lignes, additionner une colonne ou filtrer, traitez chaque bloc indépendamment et cumulez les résultats dans une liste ou un total courant. Appelez toujours l’itérateur dans une instruction with, ou recréez-le à chaque exécution du pipeline : les itérateurs ne peuvent être parcourus qu’une seule fois et ne peuvent pas être redémarrés.

import pandas as pd

total_rows = 0
total_sales = 0.0
chunk_count = 0

for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
    total_rows += len(chunk)
    total_sales += chunk['sales'].sum()
    chunk_count += 1

print(f'Chunks processed: {chunk_count}')
print(f'Total rows: {total_rows:,}')
print(f'Total sales: {total_sales:,.0f}')
print(f'Avg sales per row: {total_sales/total_rows:.2f}')

Filtrer les lignes pendant la lecture par blocs

Appliquez les filtres de lignes à l’intérieur de la boucle afin d’éliminer les données indésirables avant leur accumulation. L’utilisation de la mémoire reste ainsi faible, car seules les lignes correspondant à vos critères sont conservées. Par exemple, pour extraire toutes les lignes de la région « North » d’un fichier de 10 GB, filtrez chaque bloc avant de l’ajouter à votre liste de résultats. Le pd.concat final ne traite alors que le sous-ensemble filtré, qui est bien plus petit.

import pandas as pd

filtered_chunks = []

for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
    # Keep only North region rows
    north = chunk[chunk['region'] == 'North']
    if len(north) > 0:
        filtered_chunks.append(north)

north_df = pd.concat(filtered_chunks, ignore_index=True)
print(f'North region rows: {len(north_df):,}')
print(f'North total sales: {north_df["sales"].sum():,.0f}')

Agrégation GroupBy incrémentielle

Les agrégations GroupBy sur plusieurs blocs sont plus délicates que les simples sommes, car les groupes peuvent s’étendre sur plusieurs blocs. La méthode consiste à calculer les sommes et les comptes au niveau des groupes pour chaque bloc, à concaténer ces résultats partiels, puis à effectuer un groupby final sur les résultats partiels accumulés. N’appelez jamais groupby().mean() pour chaque bloc avant de calculer la moyenne des moyennes : cela produit des résultats incorrects lorsque la taille des groupes diffère d’un bloc à l’autre.

import pandas as pd

partials = []

for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
    # Compute sum and count per region in this chunk
    partial = chunk.groupby('region')['sales'].agg(['sum', 'count'])
    partials.append(partial)

# Combine all partial results
combined = pd.concat(partials).groupby(level=0).sum()
combined['mean'] = combined['sum'] / combined['count']

print('Regional aggregation (chunked):')
print(combined.round(2))

Spécifier des types économes en mémoire au chargement

Réduisez la mémoire utilisée lors du chargement par blocs en spécifiant à l’avance les dtypes des colonnes dans read_csv. Cela évite à Pandas d’allouer des types trop larges pour chaque bloc avant de les abandonner. Transmettez un dictionnaire tel que dtype={'region': 'category', 'sales': 'int32'} à read_csv(). Combinée à la lecture par blocs, cette méthode peut réduire la mémoire maximale utilisée à moins de 10 % de celle nécessaire au chargement naïf du fichier complet.

import pandas as pd

specified_dtypes = {
    'region': 'category',
    'sales': 'int32'
}

total_sales = 0
for chunk in pd.read_csv(
    '/tmp/large_sales.csv',
    chunksize=25000,
    dtype=specified_dtypes,
    parse_dates=['date']
):
    total_sales += chunk['sales'].sum()
    # Only 25k rows * (category + int32 + datetime) in RAM at once

print(f'Total sales (memory-efficient): {total_sales:,.0f}')

Écrire les résultats progressivement

Lorsque la sortie du traitement de chaque bloc doit également être écrite dans un fichier, écrivez chaque bloc traité au fur et à mesure plutôt que de tout accumuler en mémoire. Utilisez mode='a' (ajout) et header=False (après le premier bloc) avec to_csv(). La mémoire occupée par les données d’entrée et de sortie reste ainsi limitée à la taille d’un bloc, ce qui permet au pipeline de traiter des fichiers de taille arbitraire sur une machine disposant de peu de mémoire.

import pandas as pd
import os

output_path = '/tmp/filtered_output.csv'

# Remove previous output if it exists
if os.path.exists(output_path):
    os.remove(output_path)

first_chunk = True
for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
    # Process: keep only high-value rows
    processed = chunk[chunk['sales'] > 800].copy()
    
    # Write: header only on first chunk, append thereafter
    processed.to_csv(output_path,
                     mode='a',
                     header=first_chunk,
                     index=False)
    first_chunk = False

result = pd.read_csv(output_path)
print(f'High-value rows written: {len(result):,}')
print(f'Average sales (>800): {result["sales"].mean():.1f}')

Découvrir Dask comme solution de remplacement directe

Dask fournit une API similaire à celle de Pandas, qui exécute automatiquement les opérations de manière différée et en parallèle sur les blocs. Au lieu d’écrire une boucle manuelle de lecture par blocs, écrivez dask_df = dd.read_csv('file.csv'), puis utilisez les mêmes opérations que dans Pandas : groupby, filtrage et fusion. Appelez .compute() à la fin pour lancer l’exécution. Dask est la solution la plus pratique lorsque votre pipeline comporte plusieurs opérations complexes difficiles à implémenter manuellement avec une lecture par blocs.

# pip install dask
# import dask.dataframe as dd

# Read the large CSV as a Dask DataFrame (lazy — no data loaded yet)
# ddf = dd.read_csv('/tmp/large_sales.csv')

# Operations are lazy — no computation happens until .compute()
# result = ddf.groupby('region')['sales'].mean().compute()
# print(result)

# Key Dask advantages:
# - Automatic chunking (no manual chunksize loops)
# - Parallel execution (multi-core)
# - Familiar Pandas API
# - Works with files larger than RAM

print('Dask extends Pandas to datasets larger than RAM with minimal API changes.')

Choisir la taille des blocs

La taille idéale d’un bloc équilibre deux facteurs opposés : une taille trop petite (par exemple, 1 000 lignes) entraîne des coûts élevés pour chaque bloc (configuration des entrées-sorties du fichier, création du DataFrame) et ralentit la boucle. Une taille trop grande (par exemple, 10 millions de lignes) va à l’encontre de l’objectif en chargeant trop de données en RAM à la fois. Comme point de départ pratique, visez des blocs occupant 50 à 200 MB en mémoire. Pour un DataFrame de 10 colonnes contenant en moyenne 8 octets par valeur, 100 000 lignes représentent environ 8 MB par bloc : une valeur par défaut sûre qui laisse une marge confortable.

import pandas as pd
import timeit

# Benchmark different chunk sizes
for chunksize in [10000, 50000, 100000]:
    t = timeit.timeit(
        lambda: sum(chunk['sales'].sum()
                    for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=chunksize)),
        number=3
    )
    print(f'chunksize={chunksize:>7,}: {t/3:.3f}s per pass')

Parquet ou CSV pour les grandes quantités de données

Si vous contrôlez le format du fichier, préférez Parquet à CSV pour les grands jeux de données. Parquet est un format binaire en colonnes qui charge uniquement les colonnes demandées (sélection des colonnes), compresse bien mieux que CSV, préserve les types de données (sans nouvelle déduction au chargement) et se lit 5 à 20 fois plus rapidement qu’un CSV équivalent. Convertissez une fois un grand CSV en Parquet avec pd.read_csv('file.csv', chunksize=500000) + to_parquet, puis utilisez pd.read_parquet(columns=['col1','col2']) pour toutes les lectures suivantes.

import pandas as pd

# Convert our CSV to Parquet (do this once)
df = pd.read_csv('/tmp/large_sales.csv', parse_dates=['date'])
df['region'] = df['region'].astype('category')
df['sales'] = df['sales'].astype('int32')
df.to_parquet('/tmp/large_sales.parquet', index=False)

# Now read only the columns needed — much faster than CSV
sales_by_region = pd.read_parquet(
    '/tmp/large_sales.parquet',
    columns=['region', 'sales']
)
print('Parquet read result:')
print(sales_by_region.groupby('region')['sales'].mean().round(1))
print('\ndtypes preserved:', sales_by_region.dtypes.to_dict())

Modèle complet de pipeline par blocs

Voici un modèle complet pour traiter les fichiers volumineux : 1) spécifiez les types de données au moment de la lecture ; 2) filtrez les lignes le plus tôt possible dans la boucle ; 3) calculez les agrégations partielles pour chaque bloc (somme + compte, jamais la moyenne directement) ; 4) après la boucle, combinez les résultats partiels et calculez les statistiques finales ; 5) écrivez progressivement la sortie si les résultats sont volumineux. Ce modèle permet de traiter des fichiers de toute taille sur toute machine, à condition d’ajuster correctement chunksize.

Vérification rapide

Testez votre compréhension de la lecture par blocs présentée dans cette leçon.

Récapitulatif de la leçon

Dans cette leçon, vous avez appris que chunksize dans read_csv renvoie un itérateur fournissant un DataFrame par bloc, ce qui permet de traiter progressivement les fichiers plus volumineux que la RAM, que les agrégations partielles (somme + compte) se cumulent correctement entre les blocs alors qu’une moyenne ne peut pas être calculée directement à partir des moyennes, et que le format Parquet est la meilleure solution à long terme par rapport à CSV pour les grands jeux de données, grâce à sa compression, sa rapidité et la préservation des types de données. Le cours sur les conseils d’optimisation des performances de Pandas est maintenant terminé : vous êtes prêt à suivre les cours avancés de niveau B2 !

Gratuit pour commencer

Apprends Python avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
30
Leçons
120

Questions Fréquemment Posées

La leçon « Lecture par blocs de fichiers volumineux » est-elle gratuite ?

Oui — le texte complet de « Lecture par blocs de fichiers volumineux » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Pandas & NumPy Academy, passe à CoddyKit PRO. Le cours Pandas & NumPy Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Lecture par blocs de fichiers volumineux » ?

Traitez les fichiers qui dépassent la RAM en les lisant par blocs avec chunksize dans read_csv et en agrégeant progressivement les résultats. Tu pratiques Pandas & NumPy Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Pandas & NumPy Academy ?

Aucune expérience préalable n'est requise. Pandas & NumPy Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Lecture par blocs de fichiers volumineux » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Pandas & NumPy Academy ?

Oui. Chaque leçon Pandas & NumPy Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Profilage avec timeit et memory_profiler
  2. Éviter iterrows et les boucles Python
  3. Types de données efficaces pour réduire la mémoire
  4. Lecture par blocs de fichiers volumineux
← Retour à Pandas & NumPy Academy