Skip to content

Pandas DataFrame vers CSV : Guide Complet de to_csv()

Updated on

Vous avez nettoye les donnees, transforme chaque colonne et execute votre analyse. Maintenant vous devez partager les resultats -- et le fichier CSV que vous exportez s'ouvre avec des caracteres illisibles dans Excel, une colonne d'index non desiree, ou un fichier de 4 Go qui fait planter le portable de votre collegue. Exporter un DataFrame Pandas en CSV semble simple jusqu'a ce que l'encodage, les separateurs, la compression et les performances pour les gros fichiers transforment une seule ligne de code en une session de debogage.

Ces problemes sont courants car to_csv() possede plus de 20 parametres, et les valeurs par defaut ne correspondent pas toujours a ce que les consommateurs en aval attendent. Un mauvais encodage brise le texte non-ASCII. Un index=False manquant ajoute une colonne mysterieuse. Pas de compression transforme un jeu de donnees raisonnable en une piece jointe surdimensionnee.

La methode DataFrame.to_csv() gere tous ces cas une fois que vous savez quels parametres definir. Ce guide parcourt chaque scenario pratique -- de l'export basique a l'ecriture par blocs de DataFrames de millions de lignes -- pour que vous puissiez exporter les donnees correctement du premier coup.

📚

Utilisation de Base

L'appel le plus simple ecrit un DataFrame dans un fichier CSV dans le repertoire de travail actuel :

import pandas as pd
 
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [28, 35, 42],
    'salary': [72000, 88000, 95000]
})
 
df.to_csv('employees.csv')

Cela cree employees.csv avec le contenu suivant :

,name,age,salary
0,Alice,28,72000
1,Bob,35,88000
2,Charlie,42,95000

Remarquez la premiere colonne -- c'est l'index du DataFrame. La plupart du temps vous n'en voulez pas. Corrigez cela avec index=False :

df.to_csv('employees.csv', index=False)

Sortie :

name,age,salary
Alice,28,72000
Bob,35,88000
Charlie,42,95000

Signature Complete de la Methode

Voici la signature complete de to_csv() avec les parametres que vous utiliserez le plus souvent :

DataFrame.to_csv(
    path_or_buf=None,   # chemin du fichier ou tampon
    sep=',',            # delimiteur
    na_rep='',          # chaine pour les valeurs manquantes
    float_format=None,  # format pour les flottants
    columns=None,       # sous-ensemble de colonnes a ecrire
    header=True,        # ecrire les noms de colonnes
    index=True,         # ecrire l'index des lignes
    index_label=None,   # etiquette de colonne pour l'index
    mode='w',           # mode d'ecriture ('w', 'a', 'x')
    encoding=None,      # encodage du fichier (par defaut utf-8)
    compression='infer',# type de compression
    quoting=None,       # constante csv.QUOTE_*
    lineterminator=None,# caractere de fin de ligne
    chunksize=None,     # lignes par bloc
    date_format=None,   # format pour les dates
    errors='strict',    # gestion des erreurs d'encodage
)

Parametres Cles Expliques

sep -- Delimiteurs Personnalises

Tous les systemes ne lisent pas les virgules. Utilisez sep pour changer le delimiteur :

import pandas as pd
 
df = pd.DataFrame({
    'product': ['Widget A', 'Widget B'],
    'price': [19.99, 29.99]
})
 
# Separe par tabulations
df.to_csv('products.tsv', sep='\t', index=False)
 
# Separe par point-virgule (courant dans les parametres regionaux europeens)
df.to_csv('products_eu.csv', sep=';', index=False)
 
# Separe par pipe
df.to_csv('products.txt', sep='|', index=False)

columns -- Exporter un Sous-ensemble

Ecrivez seulement des colonnes specifiques au lieu du DataFrame entier :

import pandas as pd
 
df = pd.DataFrame({
    'id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie'],
    'email': ['a@x.com', 'b@x.com', 'c@x.com'],
    'internal_score': [0.87, 0.92, 0.78]
})
 
# Exporter uniquement les colonnes dont le client a besoin
df.to_csv('export.csv', columns=['id', 'name', 'email'], index=False)

header -- Controler les Noms de Colonnes

import pandas as pd
 
df = pd.DataFrame({
    'name': ['Alice', 'Bob'],
    'score': [85, 92]
})
 
# Pas de ligne d'en-tete
df.to_csv('no_header.csv', header=False, index=False)
 
# Noms d'en-tete personnalises
df.to_csv('custom_header.csv', header=['Nom Complet', 'Score du Test'], index=False)

na_rep -- Representer les Valeurs Manquantes

Par defaut, les valeurs NaN deviennent des chaines vides. Utilisez na_rep pour les rendre explicites :

import pandas as pd
import numpy as np
 
df = pd.DataFrame({
    'sensor': ['A', 'B', 'C'],
    'reading': [23.5, np.nan, 18.2]
})
 
# Par defaut : chaine vide pour NaN
df.to_csv('readings_default.csv', index=False)
# sensor,reading
# A,23.5
# B,
# C,18.2
 
# Marqueur explicite de valeur manquante
df.to_csv('readings_marked.csv', na_rep='NULL', index=False)
# sensor,reading
# A,23.5
# B,NULL
# C,18.2

float_format -- Controler la Precision Decimale

import pandas as pd
 
df = pd.DataFrame({
    'item': ['Widget', 'Gadget'],
    'price': [19.999999, 42.123456]
})
 
# Deux decimales
df.to_csv('prices.csv', float_format='%.2f', index=False)
# item,price
# Widget,20.00
# Gadget,42.12

date_format -- Formater les Colonnes Date/Heure

import pandas as pd
 
df = pd.DataFrame({
    'event': ['Launch', 'Review'],
    'date': pd.to_datetime(['2026-03-15 14:30:00', '2026-04-01 09:00:00'])
})
 
# Date ISO uniquement (pas d'heure)
df.to_csv('events.csv', date_format='%Y-%m-%d', index=False)
# event,date
# Launch,2026-03-15
# Review,2026-04-01

Gestion de l'Encodage et des Caracteres Speciaux

L'encodage est la cause numero un des fichiers CSV illisibles. L'encodage par defaut dans to_csv() est utf-8, qui fonctionne pour la plupart des systemes. Mais Excel sous Windows attend un BOM (Byte Order Mark) pour afficher correctement les caracteres non-ASCII.

UTF-8 (Par Defaut)

import pandas as pd
 
df = pd.DataFrame({
    'city': ['Zurich', 'Munich', 'Tokyo'],
    'greeting': ['Gruezi', 'Servus', 'Konnichiwa']
})
 
# UTF-8 standard
df.to_csv('cities.csv', index=False, encoding='utf-8')

UTF-8 avec BOM pour Excel

Si votre CSV contient des caracteres accentues, du texte CJK ou des symboles speciaux et doit s'ouvrir correctement dans Microsoft Excel :

import pandas as pd
 
df = pd.DataFrame({
    'city': ['Zurich', 'Munich', 'Sao Paulo', 'Beijing'],
    'population': [434000, 1472000, 12330000, 21540000]
})
 
# utf-8-sig ajoute un BOM qu'Excel reconnait
df.to_csv('cities_excel.csv', index=False, encoding='utf-8-sig')

Autres Encodages

import pandas as pd
 
df = pd.DataFrame({'col': ['data']})
 
# Latin-1 pour les anciens systemes europeens occidentaux
df.to_csv('legacy.csv', index=False, encoding='latin-1')
 
# Shift-JIS pour les anciens systemes japonais
df.to_csv('japanese.csv', index=False, encoding='shift_jis')
EncodageQuand l'UtiliserCompatible Excel ?
utf-8Par defaut pour la plupart des systemes, APIs, bases de donneesPartiel (pas de BOM)
utf-8-sigExcel sous Windows avec texte non-ASCIIOui
latin-1 / iso-8859-1Anciens systemes europeens occidentauxOui
shift_jisAnciens systemes japonaisOui
cp1252Windows europeen occidentalOui

Grands DataFrames : Compression et Chunking

Compression

La compression reduit la taille du fichier de 60-90% sans perte de donnees. Pandas supporte plusieurs formats :

import pandas as pd
import numpy as np
 
# Creer un grand DataFrame
df = pd.DataFrame({
    'id': range(1_000_000),
    'value': np.random.randn(1_000_000),
    'category': np.random.choice(['A', 'B', 'C', 'D'], 1_000_000)
})
 
# Compression gzip (la plus courante)
df.to_csv('large_data.csv.gz', index=False, compression='gzip')
 
# Compression zip
df.to_csv('large_data.zip', index=False, compression='zip')
 
# Compression bz2 (plus petit mais plus lent)
df.to_csv('large_data.csv.bz2', index=False, compression='bz2')
 
# Zstandard (rapide, bon ratio -- necessite le paquet zstandard)
df.to_csv('large_data.csv.zst', index=False, compression='zstd')
CompressionExtensionVitesseReduction de TailleRelecture
Aucune.csvEcriture la plus rapide0%pd.read_csv('f.csv')
gzip.csv.gzModeree70-85%pd.read_csv('f.csv.gz')
zip.zipModeree70-85%pd.read_csv('f.zip')
bz2.csv.bz2Lente75-90%pd.read_csv('f.csv.bz2')
zstd.csv.zstRapide70-85%pd.read_csv('f.csv.zst')

Pandas deduit automatiquement le format de compression a partir de l'extension du fichier, donc compression='infer' (la valeur par defaut) fonctionne generalement.

Chunksize -- Ecrire par Lots

Pour les tres grands DataFrames qui sollicitent la memoire, ecrivez par blocs :

import pandas as pd
import numpy as np
 
df = pd.DataFrame({
    'id': range(5_000_000),
    'value': np.random.randn(5_000_000)
})
 
# Ecrire 500 000 lignes a la fois
df.to_csv('huge_data.csv', index=False, chunksize=500_000)

Le parametre chunksize ne reduit pas la taille finale du fichier -- il controle combien de lignes sont ecrites sur le disque a la fois. Cela peut aider a reduire l'utilisation maximale de la memoire pendant l'operation d'ecriture.

Ecrire dans un String ou un Tampon

Vous n'ecrivez pas toujours dans un fichier. Parfois vous avez besoin du CSV sous forme de chaine pour un appel API, une insertion en base de donnees ou un traitement en memoire :

import pandas as pd
 
df = pd.DataFrame({
    'name': ['Alice', 'Bob'],
    'score': [85, 92]
})
 
# Obtenir le CSV sous forme de chaine
csv_string = df.to_csv(index=False)
print(csv_string)
# name,score
# Alice,85
# Bob,92

Ecrire dans StringIO ou BytesIO

import pandas as pd
from io import StringIO, BytesIO
 
df = pd.DataFrame({
    'x': [1, 2, 3],
    'y': [4, 5, 6]
})
 
# Tampon StringIO
buffer = StringIO()
df.to_csv(buffer, index=False)
csv_text = buffer.getvalue()
 
# Tampon BytesIO (utile pour les reponses HTTP, uploads S3)
byte_buffer = BytesIO()
df.to_csv(byte_buffer, index=False, encoding='utf-8')
csv_bytes = byte_buffer.getvalue()

Ce pattern est courant lors du telechargement de donnees CSV vers le stockage cloud (S3, GCS) sans creer de fichier local.

Ajouter a un CSV Existant

Pour ajouter des lignes a un fichier existant sans l'ecraser, utilisez mode='a' et header=False :

import pandas as pd
 
# Premier lot -- ecrire avec en-tete
df1 = pd.DataFrame({'name': ['Alice'], 'score': [85]})
df1.to_csv('results.csv', index=False)
 
# Deuxieme lot -- ajouter sans dupliquer l'en-tete
df2 = pd.DataFrame({'name': ['Bob', 'Charlie'], 'score': [92, 78]})
df2.to_csv('results.csv', mode='a', header=False, index=False)

Le fichier resultant a une ligne d'en-tete suivie des trois lignes de donnees. Omettre header=False insererait une deuxieme ligne d'en-tete au milieu des donnees.

Guillemets et Echappement

Les champs contenant le delimiteur, des retours a la ligne ou des guillemets necessitent un traitement correct. Pandas gere cela automatiquement, mais vous pouvez controler le comportement :

import pandas as pd
import csv
 
df = pd.DataFrame({
    'name': ['O\'Brien', 'Smith, Jr.', 'Alice "Ace" Wong'],
    'notes': ['Contient apostrophe', 'Contient virgule', 'Contient guillemets']
})
 
# Par defaut : guillemets seulement quand necessaire (QUOTE_MINIMAL)
df.to_csv('minimal.csv', index=False)
 
# Guillemets sur tous les champs
df.to_csv('all_quoted.csv', index=False, quoting=csv.QUOTE_ALL)
 
# Guillemets seulement sur les champs non numeriques
df.to_csv('nonnumeric.csv', index=False, quoting=csv.QUOTE_NONNUMERIC)

Comparaison des Formats d'Export : to_csv() vs to_excel() vs to_parquet()

Le choix du bon format d'export depend de qui consomme le fichier et de sa taille :

Caracteristiqueto_csv()to_excel()to_parquet()
Format de fichierTexte brutBinaire (xlsx)Binaire (colonnaire)
Lisible par l'hommeOuiVia Excel/SheetsNon
Taille du fichier (1M lignes)~50-100 Mo~30-60 Mo~5-15 Mo
Vitesse d'ecritureRapideLenteRapide
Vitesse de lectureModereeLenteTres rapide
Conservation des typesNon (tout en chaines)PartielleComplete
Necessite une lib supplementaireNonopenpyxlpyarrow / fastparquet
Support compressiongzip, zip, bz2, zstdIntegreIntegre (snappy, gzip)
Ideal pourInteroperabilite, APIs, partage rapideUtilisateurs metier, utilisateurs ExcelPipelines d'analyse, big data

Regle generale : Utilisez CSV pour partager des donnees avec des utilisateurs non techniques ou des systemes externes. Utilisez Parquet pour les pipelines internes ou la vitesse et la fidelite des types comptent. Utilisez Excel quand le destinataire a besoin de mise en forme ou de plusieurs feuilles.

Pieges Courants et Comment les Eviter

1. Colonne d'Index Non Desiree

La plainte la plus frequente. Passez toujours index=False a moins que votre index contienne des donnees significatives :

# Faux -- ajoute une colonne mysterieuse "Unnamed: 0" a la relecture
df.to_csv('data.csv')
 
# Correct
df.to_csv('data.csv', index=False)

2. Colonnes Sans Nom a la Relecture

Si vous avez exporte avec l'index puis relu le fichier, vous obtenez une colonne Unnamed: 0 :

import pandas as pd
 
# Relire un CSV exporte avec l'index
df = pd.read_csv('data.csv', index_col=0)  # indiquer a read_csv quelle colonne est l'index

3. Perte de Precision Date/Heure

Sans date_format, les colonnes date/heure sont exportees avec des horodatages complets incluant les microsecondes. Controlez cela explicitement :

import pandas as pd
 
df = pd.DataFrame({
    'ts': pd.to_datetime(['2026-01-15 08:30:00.123456'])
})
 
df.to_csv('ts.csv', index=False, date_format='%Y-%m-%d %H:%M:%S')

4. Problemes d'Arrondi des Flottants

Les nombres a virgule flottante peuvent produire des chiffres de fin inattendus :

import pandas as pd
 
df = pd.DataFrame({'val': [0.1 + 0.2]})
df.to_csv('float.csv', index=False)
# val
# 0.30000000000000004
 
df.to_csv('float_clean.csv', index=False, float_format='%.2f')
# val
# 0.30

5. Types Mixtes dans une Colonne

Si une colonne a des types mixtes (entiers et chaines), to_csv() convertit tout en chaines. Verifiez vos types de donnees avant l'export :

import pandas as pd
 
df = pd.DataFrame({'id': [1, 2, 'three']})
print(df.dtypes)
# id    object  <-- type mixte
 
# Nettoyer avant l'export
df['id'] = pd.to_numeric(df['id'], errors='coerce')
df.to_csv('clean.csv', index=False)

Visualisez Vos Donnees Avant l'Export avec PyGWalker

Avant d'exporter un DataFrame en CSV, il est utile de verifier que les donnees semblent correctes. PyGWalker (opens in a new tab) transforme n'importe quel DataFrame Pandas en une interface visuelle interactive dans Jupyter Notebook -- glissez-deposez des colonnes pour creer des graphiques sans ecrire de code de visualisation :

import pandas as pd
import pygwalker as pyg
 
df = pd.read_csv('raw_data.csv')
 
# Explorer visuellement avant l'export
walker = pyg.walk(df)
 
# Une fois satisfait, exporter
df.to_csv('verified_export.csv', index=False, encoding='utf-8-sig')

Ce flux de travail detecte les problemes comme les valeurs nulles inattendues, les valeurs aberrantes ou les mauvais types de donnees avant qu'ils n'atteignent votre consommateur CSV.

FAQ

Comment exporter un DataFrame Pandas en CSV sans l'index ?

Passez index=False a to_csv() : df.to_csv('file.csv', index=False). Cela empeche l'index des lignes d'etre ecrit comme premiere colonne. A la relecture du fichier, vous ne verrez pas de colonne supplementaire Unnamed: 0.

Comment gerer les caracteres speciaux et l'encodage lors de l'export en CSV ?

Utilisez encoding='utf-8-sig' si le CSV doit s'ouvrir correctement dans Microsoft Excel avec des caracteres non-ASCII (lettres accentuees, texte CJK). Pour les systemes standard et les APIs, le encoding='utf-8' par defaut fonctionne. Pour les systemes anciens, utilisez l'encodage specifique qu'ils requierent (latin-1, shift_jis, etc.).

Comment compresser un gros fichier CSV lors de l'export depuis Pandas ?

Ajoutez une extension de compression au nom du fichier et Pandas s'occupe du reste : df.to_csv('data.csv.gz', index=False) cree un fichier compresse en gzip. Vous pouvez aussi definir compression='gzip', 'zip', 'bz2' ou 'zstd' explicitement. Les fichiers compresses sont typiquement 70-90% plus petits et peuvent etre relus directement avec pd.read_csv().

Puis-je ajouter des donnees a un fichier CSV existant au lieu de l'ecraser ?

Oui. Utilisez mode='a' et header=False : df.to_csv('file.csv', mode='a', header=False, index=False). mode='a' ouvre le fichier en mode ajout, et header=False empeche l'ecriture d'un en-tete duplique au milieu du fichier.

Quelle est la difference entre to_csv() et to_parquet() dans Pandas ?

to_csv() produit un fichier texte lisible par l'homme mais perd les informations de type (tout devient des chaines). to_parquet() cree un fichier binaire compact qui preserve les types de donnees (entiers, flottants, dates), se lit 5-10x plus vite et est 5-10x plus petit. Utilisez CSV pour le partage avec des utilisateurs non techniques ou des systemes externes. Utilisez Parquet pour les pipelines de donnees internes ou la performance et la fidelite des types comptent.

Conclusion

DataFrame.to_csv() est la methode standard pour exporter des donnees Pandas vers des fichiers CSV. Pour des exports propres, passez toujours index=False. Utilisez encoding='utf-8-sig' quand la compatibilite Excel est importante. Compressez les gros fichiers avec gzip ou zstd pour reduire la taille de 70-90%. Controlez la precision decimale avec float_format, gerez les valeurs manquantes avec na_rep et ajoutez aux fichiers existants avec mode='a'. Pour les pipelines de donnees ou la conservation des types et la vitesse comptent, envisagez to_parquet() a la place. Avant d'exporter, verifiez visuellement vos donnees avec des outils comme PyGWalker pour detecter les problemes tot.

📚