La logique derrière pandas drop duplicates est simple : repérer les lignes identiques, puis décider lesquelles conserver sans casser le reste du traitement. En pratique, je l’utilise autant pour nettoyer des exports CSV que pour fiabiliser des données issues d’API, de formulaires ou de logs. Le point important n’est pas seulement de supprimer des doublons, mais de le faire sur les bonnes colonnes, dans le bon ordre, avec le bon niveau de contrôle.
Ce qu’il faut vérifier avant de dédupliquer un DataFrame
- `drop_duplicates()` renvoie un nouveau DataFrame par défaut, donc l’original reste intact si `inplace=False`.
- L’index n’entre pas dans la détection des doublons ; ce sont les valeurs des colonnes qui comptent.
- `keep='first'` est le réglage par défaut, mais `keep='last'` et `keep=False` changent vraiment le résultat.
- `subset` permet de dédupliquer sur certaines colonnes seulement, ce qui évite d’écraser des lignes utiles.
- `ignore_index=True` remet un index propre quand on veut repartir d’un tableau compact.
Ce que fait vraiment la suppression des doublons
Dans Pandas, `drop_duplicates()` retire les lignes répétées d’un DataFrame en comparant les valeurs des colonnes, pas le numéro de ligne. C’est un détail qui compte, parce que deux enregistrements peuvent avoir un index différent et rester considérés comme doublons si le contenu est identique. La méthode est simple à utiliser, mais elle n’est fiable que si vous savez exactement quelles colonnes définissent l’unicité de vos données.
Je vois souvent une confusion entre "ligne dupliquée" et "ligne inutile". Ce n’est pas la même chose. Une ligne peut sembler répétée visuellement, tout en portant une information différente dans une colonne cachée, un horodatage ou un identifiant métier. C’est pour cela que je conseille de vérifier le schéma des données avant de supprimer quoi que ce soit. Pour les jeux de données propres, la méthode suffit. Pour les données métier, il faut parfois décider d’abord quelle version de l’enregistrement mérite d’être conservée.
Par défaut, Pandas retourne un nouveau DataFrame. Si vous modifiez le flux de travail, c’est souvent plus sûr que d’écraser l’objet d’origine. En production, cette discipline évite des effets de bord difficiles à diagnostiquer quand plusieurs étapes réutilisent la même variable. Une fois ce cadre posé, il faut regarder les paramètres qui changent réellement le résultat.
Les paramètres qu’il faut regarder en premier
Je commence presque toujours par trois réglages : subset, keep et ignore_index. Ils déterminent si vous nettoyez correctement le tableau ou si vous effacez trop de données par accident. Le paramètre inplace existe, mais je l’utilise rarement dans un pipeline moderne, parce qu’il rend les étapes moins lisibles et les retours en arrière plus pénibles.
| Paramètre | Rôle | Quand je l’utilise |
|---|---|---|
subset |
Choisit les colonnes qui servent à repérer les doublons | Quand l’unicité ne dépend pas de toutes les colonnes |
keep |
Décide quelle occurrence garder | Quand l’ordre des lignes a une valeur métier |
ignore_index |
Réindexe le résultat de 0 à n-1 | Après un nettoyage final ou pour un export propre |
inplace |
Modifie l’objet courant au lieu d’en renvoyer un nouveau | Très rarement, seulement dans un script simple |
Un usage courant ressemble à ceci :
df_clean = df.drop_duplicates(
subset=["email"],
keep="first",
ignore_index=True
)Ici, je conserve une seule ligne par adresse e-mail et je repars avec un index compact. Si je veux garder la trace du DataFrame d’origine, je laisse inplace=False et j’assigne le résultat dans une nouvelle variable. Le réglage keep est le plus visible, parce qu’il décide concrètement quelle ligne survit.

Garder la première ligne, la dernière ou aucune
Le comportement de keep est souvent mal compris, alors qu’il est central. Il ne choisit pas une "meilleure" ligne au sens métier, il ne fait que conserver l’occurrence demandée selon l’ordre actuel du DataFrame. C’est pourquoi un tri préalable peut changer complètement le résultat.
Valeur de keep
|
Effet | Cas d’usage typique |
|---|---|---|
first |
Conserve la première occurrence de chaque doublon | Import brut, flux déjà ordonné dans le bon sens |
last |
Conserve la dernière occurrence de chaque doublon | Vous voulez privilégier la version la plus récente dans un tableau déjà trié |
False |
Supprime toutes les lignes qui ont un doublon | Contrôle qualité, liste strictement unique |
import pandas as pd
df = pd.DataFrame({
"client_id": [10, 10, 11, 12, 12],
"nom": ["Amina", "Amina", "Nassim", "Lea", "Lea"],
"ville": ["Paris", "Paris", "Lyon", "Lille", "Lille"],
})
premiere = df.drop_duplicates(keep="first")
derniere = df.drop_duplicates(keep="last")
aucune = df.drop_duplicates(keep=False)Dans cet exemple, keep=False retire les lignes répétées au lieu d’en garder une version. C’est utile quand je veux identifier les valeurs vraiment uniques, pas seulement nettoyer visuellement un tableau. Si votre flux contient des enregistrements quasi identiques mais pas strictement égaux, cette méthode ne les traitera pas comme des doublons. Elle compare les valeurs, pas l’intention humaine derrière les données. Quand on ne veut pas comparer tout le tableau, subset devient alors le vrai levier.
Dédupliquer seulement sur les bonnes colonnes
Dans la plupart des cas réels, je ne veux pas comparer toutes les colonnes. Une même personne peut apparaître plusieurs fois avec des métadonnées différentes, un statut différent ou une source d’import différente. Si je compare tout le DataFrame, je risque de laisser passer des doublons qui sont pourtant des doublons métier, ou au contraire de supprimer des lignes qui n’auraient pas dû disparaître.
df = pd.DataFrame({
"email": ["a@exemple.fr", "a@exemple.fr", "b@exemple.fr"],
"nom": ["Alice", "Alice", "Bruno"],
"source": ["formulaire", "import", "api"],
})
par_email = df.drop_duplicates(subset=["email"], keep="first")Ici, je considère que l’adresse e-mail définit l’unicité. Les autres colonnes peuvent différer, mais elles ne comptent pas pour la déduplication. C’est exactement ce qu’on attend quand un e-mail sert d’identifiant fonctionnel. Si l’unicité dépend de plusieurs champs, il suffit de les passer ensemble à subset :
par_identite = df.drop_duplicates(subset=["nom", "source"], keep="first")Le principe est simple : deux lignes sont considérées comme doublons seulement si toutes les colonnes listées dans subset ont la même valeur. Cette logique devient très utile sur des jeux de données clients, produits ou commandes, où l’identifiant métier dépend de plusieurs attributs à la fois. Quand l’ordre des lignes commence à compter, il faut alors regarder de près le tri préalable et l’inspection des doublons.
Choisir la bonne ligne quand l’ordre compte
La méthode ne sait pas quelle ligne est "la meilleure". Elle garde juste la première ou la dernière selon le tri actuel. En pratique, c’est là que beaucoup de traitements deviennent fragiles, parce qu’un DataFrame non trié peut produire un résultat différent d’un jour à l’autre. Si la version à conserver dépend d’une date de mise à jour, je trie d’abord, puis je déduplique.
Quand un tri préalable change tout
df_recent = (
df.sort_values("updated_at", ascending=False)
.drop_duplicates(subset=["user_id"], keep="first")
)Dans ce schéma, je garde la version la plus récente de chaque utilisateur. Le tri en ordre décroissant fait que la ligne la plus récente arrive en premier, puis keep="first" conserve précisément cette version. Si je veux l’inverse, je trie en ordre croissant. Cette petite combinaison est souvent plus fiable qu’un traitement improvisé, parce qu’elle rend la règle lisible dans le code.
Lire aussi : Shebang Python - Le guide complet pour des scripts fiables
Vérifier avant de supprimer
doublons = df[df.duplicated(subset=["user_id"], keep=False)]
nombre_de_lignes_dupliquees = df.duplicated(subset=["user_id"], keep=False).sum()Je m’en sers pour auditer le problème avant l’effacement. Le masque retourné par duplicated(..., keep=False) marque toutes les lignes concernées, ce qui permet de les inspecter, de les exporter ou de les comparer avant de trancher. C’est souvent plus prudent que de lancer directement un nettoyage destructif. Avant de fermer le fichier, quelques réflexes évitent les erreurs discrètes.
Les réflexes que j’applique avant d’effacer des doublons en production
- Je garde toujours une copie du jeu de données brut, même si le traitement paraît banal.
- Je commence par compter et afficher les lignes dupliquées avec
duplicated(..., keep=False). - Je définis explicitement
subsetau lieu de faire confiance à toutes les colonnes par défaut. - Je trie avant de dédupliquer dès qu’une notion de priorité, d’ancienneté ou de fraîcheur existe.
- Je n’utilise
ignore_index=Truequ’à la fin, quand l’index d’origine n’a plus de valeur. - Je laisse
inplace=Falsedans la majorité des cas pour garder un pipeline plus facile à relire.
Au fond, `drop_duplicates` n’est pas un outil de nettoyage aveugle, mais une règle de sélection très précise. Plus vous définissez clairement ce qu’est un doublon dans votre contexte, plus le résultat est fiable, lisible et simple à maintenir. C’est cette discipline qui fait la différence entre un script qui "marche" et un traitement que l’on peut vraiment faire évoluer sans surprise.