Pour les lignes strictement identiques, en gardant l'en-tête et l'ordre d'origine :
awk 'NR==1 || !seen[$0]++' input.csv > deduped.csv
Cela règle le cas facile, et le cas facile est plus rare qu'il n'en a l'air. La plupart des « doublons » d'un fichier de travail ne sont pas des lignes identiques, mais deux enregistrements de la même personne avec une casse différente, une espace en fin de champ ou un numéro de téléphone mis à jour. Supprimer le mauvais, c'est perdre des données ; l'ordre des opérations compte donc : décidez ce qui rend deux lignes identiques, regardez ce qui les différencie, et seulement ensuite supprimez.
Étape un : définir la clé
Un doublon, ce sont deux lignes qui décrivent la même chose. Les colonnes qui l'établissent relèvent d'une décision sur vos données, pas d'une propriété du fichier.
- Un doublon de ligne entière, tous les champs identiques, est presque toujours une erreur : un double import, une tâche relancée, un ajout exécuté deux fois. Vous pouvez le supprimer sans risque.
- Un doublon de clé, même
emailou mêmeorder_idmais tout le reste différent, est une question de données. L'une des lignes est probablement plus récente ou plus complète, et c'est à vous de choisir.
Inverser les deux est la façon classique de perdre des enregistrements. Dédoublonner sur name dans une liste de clients supprimera sans état d'âme deux personnes différentes qui s'appellent James Smith.
Étape deux : compter avant de supprimer
Ne lancez jamais un dédoublonnage à l'aveugle. Regardez ce que vous allez retirer :
duckdb -c "SELECT email, count(*) n FROM read_csv('input.csv') GROUP BY email HAVING n > 1 ORDER BY n DESC LIMIT 20"
Deux chiffres vous disent si votre clé est la bonne. Si le nombre de doublons se compte sur les doigts, ce sont sans doute de vraies saisies en double. Si un tiers du fichier est « dupliqué », la clé est mauvaise : vous comparez quelque chose qui n'a jamais été unique.
Regardez ensuite un cas précis en entier, l'étape que tout le monde saute :
duckdb -c "SELECT * FROM read_csv('input.csv') WHERE email = '[email protected]'"
C'est là que vous découvrez que les deux lignes diffèrent justement dans la colonne qui vous importait.
Étape trois : choisir la ligne qui reste
Quand vous savez que les lignes diffèrent, « supprimer les doublons » devient « garder la bonne ». Trois règles, à peu près classées selon la fréquence où elles sont justes :
Garder la plus récente. S'il y a un horodatage, c'est généralement la réponse.
duckdb -c "COPY (SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY email ORDER BY updated_at DESC) rn FROM read_csv('input.csv')) WHERE rn = 1) TO 'deduped.csv' (HEADER)"
Garder la plus complète. Sans horodatage, trier selon le nombre de champs non vides est un bon substitut, car l'enregistrement le plus rempli est souvent le plus tardif. Triez par (col_a IS NOT NULL)::INT + (col_b IS NOT NULL)::INT + … et prenez la première.
Fusionner les deux. Parfois chaque ligne contient ce qui manque à l'autre. C'est courant et il n'y a pas de raccourci : c'est un coalesce par colonne, et pour un petit ensemble mieux vaut le faire à la main que de mal automatiser pour un gros.
Quel que soit votre choix, écrivez les lignes écartées dans un second fichier avant de les supprimer. Un dédoublonnage irréversible, vous le regretterez à un moment ou à un autre dans les quinze jours qui suivent.
Les quasi-doublons, c'est-à-dire presque tous
La correspondance exacte rate la majorité des doublons réels. Normalisez d'abord, comparez ensuite, et conservez les valeurs d'origine.
duckdb -c "SELECT lower(trim(email)) k, count(*) n FROM read_csv('input.csv') GROUP BY k HAVING n > 1"
Les normalisations à appliquer, à peu près par ordre de rendement :
- La casse.
[email protected]et[email protected]sont la même boîte mail. - Les espaces. Les espaces en fin de champ venus d'un copier-coller sont invisibles et extrêmement fréquents.
trim()retire ceux du début et de la fin ; unreplacetraite les espaces insécables qui arrivent des formulaires web. - La ponctuation dans les identifiants. Les numéros
+44 20 7946 0958,02079460958et(020) 7946 0958sont un seul numéro. Supprimez tout ce qui n'est pas un chiffre avant de comparer. - Les points Gmail et les adresses avec plus.
[email protected]arrive dans la même boîte que[email protected]. Que ce soit un doublon dépend de ce que vous dédoublonnez : des personnes ou des comptes.
Ce qu'il ne faut pas faire automatiquement : la correspondance floue sur les noms. « Jon Smith » et « John Smith » peuvent être la même personne ou deux collègues, et un seuil de similarité adapté à un fichier est mauvais pour le suivant. Générez les paires candidates, relisez-les, puis agissez.
L'éditeur SQL et l'éditeur de filtres visuels forment les deux moitiés de ce travail : un GROUP BY pour trouver les clés en double, puis un filtre pour lire chaque ligne qui en partage une, sans rien charger au préalable dans une base de données.
Ce que ça faitDans un tableur
Excel et Sheets ont tous deux une commande Supprimer les doublons (Remove Duplicates), avec une particularité à connaître avant de l'utiliser : elle garde la première occurrence et supprime le reste, sans moyen de dire laquelle est la première. L'ordre dans lequel se trouvait la feuille décide quel enregistrement survit.
Triez donc délibérément avant de l'exécuter. Triez par horodatage décroissant, et « garder la première » devient « garder la plus récente », ce que vous vouliez en général.
L'autre approche en tableur, une colonne auxiliaire avec COUNTIF, est plus lente mais non destructive, et elle vous montre les doublons au lieu de les retirer. Sur un gros fichier, c'est aussi ce qui fera planter Excel, car COUNTIF sur un demi-million de lignes est quadratique.
Sur un téléphone
Sur un téléphone, la version réaliste n'est pas un passage de dédoublonnage complet. Il s'agit de trier par la colonne suspecte, de faire défiler et de voir les répétitions côte à côte, ce qui est le moyen le plus rapide de savoir si un fichier a un problème de doublons.
Une fois que vous les voyez, filtrer sur une clé et lire les quelques lignes qui la partagent répond à la seule question qui compte : est-ce le même enregistrement, ou deux enregistrements qui partagent un champ par hasard ?
Triez par n'importe quelle colonne comme dans Excel, puis supprimez des lignes avec le filtre actif en toute sécurité : les lignes masquées sont protégées, donc une suppression ne touche jamais les données hors du filtre. L'annulation couvre tout, et c'est ce qui rend raisonnable de le faire sur un téléphone.
Ce que ça faitVérifier
Trois chiffres, qui doivent concorder :
wc -l input.csv deduped.csv
duckdb -c "SELECT count(*) rows, count(DISTINCT email) keys FROM read_csv('deduped.csv')"
rows et keys doivent maintenant être égaux. Sinon, le dédoublonnage ne s'est pas appliqué à tous les groupes. Et input − deduped doit être égal au nombre de lignes que vous comptiez supprimer, celui de l'étape deux. S'il en a retiré davantage, la clé était plus large ou plus étroite que prévu, et le fichier des lignes écartées que vous avez conservé sauve maintenant votre après-midi.