Pourquoi read_csv reste incontournable
Parce qu’il transforme un simple fichier texte (CSV, TSV, “CSV Excel” au point-virgule, CSV compressé, flux HTTP/S3…) en DataFrame exploitable en 1 ligne. La clé, c’est de spécifier tôt séparateur, encodage, types et dates pour éviter les mauvaises surprises (colonnes “object”, dates non reconnues, virgule décimale, etc.).
,, UTF-8)import pandas as pd
df = pd.read_csv("data.csv") # heuristiques par défaut
;, décimale ,)df = pd.read_csv(
"export_excel.csv",
sep=";", # point-virgule
decimal=",", # virgule décimale
thousands="\u00A0" # NBSP souvent présent comme séparateur de milliers
)
dtypes = {"id": "Int64", "categorie": "category", "prix_ht": "float64"}
df = pd.read_csv(
"ventes.csv",
sep=";",
decimal=",",
parse_dates=["date_vente"],
dayfirst=True, # format français DD/MM/YYYY
dtype=dtypes,
na_values=["", "NA", "N/A", "-", "null"]
)
sep=";" pour les exports FR/Excel.header=0 (défaut) si la première ligne contient les noms de colonnes.names=[...] pour imposer les noms (utile si fichier sans en-tête).usecols=[...] charge uniquement les colonnes utiles (mémoire + vitesse).encoding="utf-8" (recommandé), ou encoding="latin-1" / "cp1252" si accents cassés.encoding_errors="ignore" ou "replace" pour survivre aux caractères illisibles (mieux vaut loguer ces cas pour correction amont).decimal="," et thousands="\u00A0" (NBSP) ou " " selon vos fichiers., et . pour les décimales dans un même champ : normalisez tôt.parse_dates=[...] + dayfirst=True pour DD/MM/YYYY.df = pd.read_csv("logs.csv", dtype={"ts": "string"})
df["ts"] = pd.to_datetime(df["ts"], utc=True, errors="coerce") # format explicite si connu
true_values=["OUI","Oui","YES","1"], false_values=["NON","No","0"].na_values=[...] pour compléter la liste par défaut (ex. "-", "NULL").keep_default_na=True (défaut) : garde la liste standard de NA.on_bad_lines="skip" (ou "warn") pour ignorer/avertir sur les lignes mal formées.engine="python" : df = pd.read_csv("cassé.csv", on_bad_lines="skip", engine="python")dtype={"code":"string", "qte":"Int64", "prix":"float64"} :Int64 (nullable), string (pandas), category (faible cardinalité) = RAM plus basse et erreurs plus tôt.dtype_backend="pyarrow" peut réduire l’empreinte mémoire et accélérer certaines opérations (selon votre stack).engine="c" (rapide, défaut) ; engine="python" (plus tolérant).usecols (colonne subset)dtype (évite mixes dtypes)chunksize=... (streaming)memory_map=True (selon OS/fichiers)low_memory=False si vous voulez éviter les colonnes “mixtes” (au prix de plus de RAM).total = 0.0
for chunk in pd.read_csv(
"big.csv",
usecols=["montant"],
dtype={"montant": "float64"},
chunksize=1_000_000):
total += chunk["montant"].sum()
print(total)
from pathlib import Path
import pandas as pd
dtypes = {"id": "Int64", "montant": "float64", "client": "string"}
files = sorted(Path("data").glob("*.csv"))
df = pd.concat(
(pd.read_csv(f, sep=";", decimal=",", usecols=["id","client","montant"], dtype=dtypes)
for f in files),
ignore_index=True
)
df = pd.read_csv("https://exemple.com/datasets/ventes.csv")df = pd.read_csv("ventes_2024.csv.gz") # gzip df = pd.read_csv("ventes.zip") # si le ZIP contient un seul CSVdf = pd.read_csv("s3://mon-bucket/ventes.csv", storage_options={"anon": False}) (Adaptez vos credentials selon l’environnement.)df = pd.read_csv("source.csv", usecols=["ID","Nom client","CA (HT)"])
df = df.rename(columns={"ID":"id", "Nom client":"client", "CA (HT)":"ca_ht"})[["id","client","ca_ht"]]
# Valeurs oui/non hétérogènes -> booléen propre
df = pd.read_csv(
"clients.csv",
converters={"actif": lambda x: str(x).strip().lower() in {"oui","yes","true","1"}}
).astype({"actif": "boolean"})
ATTENDU_COLS = {"id","client","date_vente","montant"}
df = pd.read_csv("ventes.csv", sep=";", decimal=",", parse_dates=["date_vente"])
manquantes = ATTENDU_COLS - set(df.columns)
if manquantes:
raise ValueError(f"Colonnes manquantes: {sorted(manquantes)}")
# Contrôle types simples
assert pd.api.types.is_datetime64_any_dtype(df["date_vente"])
assert pd.api.types.is_numeric_dtype(df["montant"])
;, virgule décimale, NBSP)def read_csv_fr(path, *, cols=None, dtypes=None, parse_dates=None):
import pandas as pd
return pd.read_csv(
path,
sep=";",
decimal=",",
thousands="\u00A0",
usecols=cols,
dtype=dtypes,
parse_dates=parse_dates,
dayfirst=True,
na_values=["", "NA", "N/A", "-", "null"]
)
from collections import Counter
import pandas as pd
def stats_par_client(path, chunksize=500_000):
totaux = Counter()
for chunk in pd.read_csv(
path,
usecols=["client","montant"],
dtype={"client":"string", "montant":"float64"},
chunksize=chunksize
):
totaux.update(chunk.groupby("client")["montant"].sum().to_dict())
return pd.Series(totaux, name="ca_ht").sort_values(ascending=False).to_frame()
df = pd.read_csv(
"source_irreguliere.csv",
engine="python",
on_bad_lines="skip",
sep=";"
)
sep=";", decimal=",", thousands=NBSP).utf-8, sinon latin-1/cp1252) + encoding_errors.category si faible cardinalité).dayfirst=True (ou conversion après lecture si format complexe).true_values/false_values.engine="python" si fichiers irréguliers.UnicodeDecodeError : essayez encoding="latin-1" ou encoding_errors="replace".dtype et/ou decimal/thousands.parse_dates + dayfirst, ou conversion après lecture avec pd.to_datetime(..., format=..., errors="coerce").low_memory=False et/ou types imposés, ou nettoyez amont.chunksize, usecols, dtype serrés, éventuellement dtype_backend="pyarrow" si votre environnement le permet.
pandas.read_csv# Essai en UTF-8 avec BOM (souvent depuis Excel/Windows)
df = pd.read_csv("data.csv", encoding="utf-8-sig")
# Si accents cassés :
df = pd.read_csv("data.csv", encoding="latin-1") # ou "cp1252"
# En mode “je préfère charger et corriger après” :
df = pd.read_csv("data.csv", encoding="utf-8", encoding_errors="replace")
, vs ; vs \t) → auto-détection# Heuristique Sniffer (nécessite engine='python')
df = pd.read_csv("data.csv", sep=None, engine="python")
Si vous connaissez le séparateur, imposez-le (plus fiable).
; + virgule décimale + milliers insécablesdf = pd.read_csv(
"export.csv",
sep=";",
decimal=",",
thousands="\u00A0" # NBSP très fréquent
)
import csv
df = pd.read_csv(
"notes.csv",
sep=";",
engine="python", # plus tolérant pour sauts de ligne intégrés
quotechar='"',
doublequote=True # "" devient " dans le champ
)
import csv
df = pd.read_csv(
"weird.csv",
sep=";",
engine="python",
quotechar="'", # guillemet simple comme délimiteur
doublequote=False,
escapechar="\\", # séquence d’échappement \'
)
# Sauter des lignes d’en-tête non tabulaires
df = pd.read_csv("rapport.csv", skiprows=3) # ignore 3 premières
# Multi-index de colonnes (ex. 2 lignes d’en-têtes)
df = pd.read_csv("multiheader.csv", header=[0,1])
# Pied de page (nécessite engine='python')
df = pd.read_csv("rapport.csv", skipfooter=2, engine="python")
df = pd.read_csv(
"messy.csv",
sep=";",
engine="python", # tolère colonnes inégales
on_bad_lines="skip" # ou "warn" pour diagnostiquer
)
# Lire en chaîne (string) pour ne pas perdre les zéros
df = pd.read_csv("codes.csv", dtype={"code_postal": "string", "siret": "string"})
df = pd.read_csv("ids.csv", dtype={"id": "string"}) # pas en float !
# Si le format est stable (FR) :
df = pd.read_csv("ventes.csv", sep=";", parse_dates=["date"], dayfirst=True)
# Si les formats varient → lire en string puis convertir :
df = pd.read_csv("ventes.csv", dtype={"date": "string"})
df["date"] = pd.to_datetime(
df["date"],
errors="coerce", # valeurs inconvertibles → NaT
dayfirst=True # aide pour 01/02/2025 (1er février)
)
# ISO 8601 avec 'Z' (UTC)
df = pd.read_csv("log.csv", dtype={"ts": "string"})
df["ts"] = pd.to_datetime(df["ts"], utc=True, errors="coerce")
# Epoch (secondes)
df = pd.read_csv("events.csv", dtype={"ts": "Int64"})
df["ts"] = pd.to_datetime(df["ts"], unit="s", utc=True, errors="coerce")
# Lire en string, nettoyer, puis convertir
df = pd.read_csv("mix.csv", dtype={"montant": "string"})
df["montant"] = (df["montant"]
.str.replace("\u00A0", "", regex=False) # suppr. NBSP
.str.replace(",", ".", regex=False)) # virgule → point
df["montant"] = pd.to_numeric(df["montant"], errors="coerce")
dtypes = {"id":"Int64", "client":"string", "ca":"float64"}
df = pd.read_csv("ventes.csv", usecols=["id","client","ca"], dtype=dtypes)
total = 0.0
for chunk in pd.read_csv("big.csv", usecols=["montant"], dtype={"montant":"float64"}, chunksize=1_000_000):
total += chunk["montant"].sum()
from pathlib import Path
import pandas as pd
files = sorted(Path("data").glob("*.csv"))
frames = (pd.read_csv(f, sep=";", decimal=",", usecols=["id","montant"]) for f in files)
df = pd.concat(frames, ignore_index=True)
import zipfile, io, pandas as pd
rows = []
with zipfile.ZipFile("bundle.zip") as z:
for name in z.namelist():
if name.lower().endswith(".csv"):
with z.open(name) as f:
rows.append(pd.read_csv(io.TextIOWrapper(f, encoding="utf-8")))
df = pd.concat(rows, ignore_index=True)
import csv
df = pd.read_csv(
"data.tsv",
sep="\t",
quotechar='"',
engine="python", # gère mieux les cas tordus
quoting=csv.QUOTE_MINIMAL
)
df = pd.read_csv("mesures.csv", comment="#") # ignore les lignes commençant par #
df = pd.read_csv("data.csv", sep=";", skipinitialspace=True)
df = pd.read_csv(
"clients.csv",
true_values=["OUI","Oui","YES","True","1"],
false_values=["NON","No","False","0"]
).astype({"actif":"boolean"})
ATTENDU = {"id":"Int64","date":"datetime64[ns]","montant":"float64"}
df = pd.read_csv("ventes.csv", sep=";", parse_dates=["date"], dtype={"id":"Int64","montant":"float64"})
manquantes = set(ATTENDU) - set(df.columns)
if manquantes:
raise ValueError(f"Colonnes manquantes : {sorted(manquantes)}")
assert pd.api.types.is_datetime64_any_dtype(df["date"])
assert pd.api.types.is_numeric_dtype(df["montant"])
df = pd.read_csv(
"irreg.csv",
engine="python",
on_bad_lines="skip",
sep=None, # tentative d’auto-détection
dtype="string" # tout en string → nettoyage en aval
)
def read_csv_fr(path, *, cols=None, dtypes=None, parse_dates=None):
import pandas as pd
return pd.read_csv(
path,
sep=";",
decimal=",",
thousands="\u00A0",
usecols=cols,
dtype=dtypes,
parse_dates=parse_dates,
dayfirst=True,
na_values=["", "NA", "N/A", "-", "null"]
)
skipfooter → exige engine="python".sep=None (auto-détection) → exige engine="python".low_memory=False ou imposez dtype.string (pas en float64).usecols, dtype, chunksize, agrégations par morceaux.Différence engine="c" vs "python" ?"c" est très rapide mais strict ; "python" est plus tolérant (utile avec on_bad_lines) mais plus lent.
Int64 vs int64 ?Int64 est nullable (accepte NA), int64 ne l’est pas. Préférez Int64 quand des manquants sont possibles.
Quand utiliser category ?
Quand la cardinalité de la colonne est faible (codes, états, pays). Gain de RAM et groupby/joins plus efficaces.
Deux outils concrets pour piloter la qualité sans alourdir vos équipes Un système qualité n’avance…
Un chantier se gagne souvent avant même l’arrivée des équipes. Quand tout est clair dès…
Le mariage a du sens quand il repose sur une décision libre, mûrie et partagée.…
Une étude de cas réussie commence par une structure sûre. Ce modèle Word vous guide…
Les soft skills se repèrent vite sur une fiche, mais elles ne pèsent vraiment que…
Outil de comparaison et repérage des offres étudiantes Choisir des verres progressifs ressemble rarement à…
This website uses cookies.