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.
Le modèle - Rapport moral du président d’association en PDF - qui se lit facilement,…
Exemple clair, prêt à télécharger, pour présenter votre activité avec un rendu premium Une présentation…
On croit souvent qu’un frigo “fait le job” tant qu’il est froid au moment où…
Visualiser les forces réelles d’une équipe ne relève plus de l’intuition lorsqu’une matrice des compétences…
Comprendre, structurer et rédiger un document fondateur clair, crédible et inspirant Rédiger les statuts d’une…
Gérez les pannes, bugs, coupures réseau et alertes sécurité avec une procédure claire, structurée et…
This website uses cookies.